V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
miniyao
V2EX  ›  Python

if foobar != None 和 if foobar is not None 是完全等价的吗?

  •  
  •   miniyao · 2018-03-31 12:11:48 +08:00 · 3244 次点击
    这是一个创建于 2465 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有两个基础的问题,都有用过,不确定哪些场景完全等价 /不等价:

    1. if foobar != None 和 if foobar is not None 是完全等价吗?
    
    2. if foobar is not None 和 if foobar 是完全等价吗?
    
    12 条回复    2018-03-31 22:34:13 +08:00
    jingniao
        1
    jingniao  
       2018-03-31 12:15:58 +08:00   ❤️ 1
    都不等价
    lyc8801
        2
    lyc8801  
       2018-03-31 12:18:41 +08:00   ❤️ 1
    不等,is,is not 好像是用来判断引用的对象是不是同一个,==,!=这种是判断值的
    zeyexe
        3
    zeyexe  
       2018-03-31 12:23:56 +08:00   ❤️ 1
    1. 参考 https://stackoverflow.com/a/1504742
    2. if foobar 是判断真值,foobar=0 的时候 if foobar 也是 False
    iEverX
        4
    iEverX  
       2018-03-31 12:33:30 +08:00 via Android
    @lyc8801 对于 None 来说,==和 is 应该没差别,语意上可能不一样,结果上应该是恒等的。
    binux
        5
    binux  
       2018-03-31 13:22:03 +08:00
    @iEverX #4 重载 __eq__
    gwki
        6
    gwki  
       2018-03-31 13:23:07 +08:00   ❤️ 5
    先弄清 value 和 identity
    value 可能会变,多个对象可以拥有相同的 value
    identity 自对象创建到其被销毁都不会变,每一个对象的 identity 都不同,id(x)可以返回 x 对象的 identity
    CPython 将 id(x)实现为返回存储对象的内存地址

    is 测试两边运算对象的 id 是否相同,当且仅当对象 x 和 y 的 id(x) == id(y)时 is 返回 True
    is not 返回与 is 相反的结果

    !=, ==, >, <等叫做值比较,而值比较的默认行为可以通过修改__eq__,__ne__等函数来改变

    if 在一个对象的__bool__()不返回 False 和__len__()不返回 0 的情况下认定对象为真,还有,语言内置的常量 None 和 False 被认为是假的

    1. if foobar != None 和 if foobar is not None 是完全等价吗?
    在下面这种或与其类似的情况下是完全等价的:
    class Hello:
    def __ne__(self, other):
    print("Excalibur !")
    return (self is not other)

    foobar = Hello()
    print(foobar is not None)
    print(foobar != None)
    一般而言,是不完全等价的
    因为 is not 测试 foobar 的 id 和 None 的 id 是否相同,而!=测试 foobar 的值和 None 的值是否相同

    2. if foobar is not None 和 if foobar 是完全等价吗?
    一般情况下是不等价的,因为前者测试 id 是否相同,后者测试 foobar 的__bool__()或__len__()
    当然你也可以修改 foobar 的__bool__函数
    以上结论基于 Python3.6 的官方文档^^/
    iEverX
        7
    iEverX  
       2018-03-31 13:29:46 +08:00
    @binux 说的是
    scriptB0y
        8
    scriptB0y  
       2018-03-31 14:38:23 +08:00   ❤️ 1
    楼上 @gwki 说的很清楚了!

    但是对于 None 来说有一点区别,你看很多 Python 代码就会发现:大部分情况下我们用 if foo is None 来做判断,因为 None 在 Python 中是一个全局唯一变量。官方文档中说:Since None is a singleton, testing for object identity (using == in C) is sufficient. 所以官方是推荐用 id 来 check 的。

    即:None 只有一个,不存在值为 None 但是与 id(None) 不相等的情况。

    写作 if foo != None 有点不 Pythonic (反正我是没这么见过哈哈哈)。

    问题 2:

    foo = 0
    if foo 判断为假,
    if foo is not None 判断为真。所以 is 判断的是 id 相同(对于 None 来说判断 id 相同和判断值相同没有太大区别,反正只有 1 个)。

    所以二者是不一样的,除了 None 之外,文档( https://docs.python.org/3.6/library/stdtypes.html#truth-value-testing )还有下面的判断为假:

    - constants defined to be false: None and False.
    - zero of any numeric type: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
    - empty sequences and collections: '', (), [], {}, set(), range(0)

    再啰嗦一点,对于不可变对象,为了避免重复创建,Python 做了驻留处理。比如下面代码:

    >>> s1 = "ABC"
    >>> s2 = "ABC"
    >>> s1 is s2
    True

    但是我们实际比较二者的时候,应该用 s1 == s2。因为驻留操作是 CPython 的实现细节。副作用不应该被依赖。
    scriptB0y
        9
    scriptB0y  
       2018-03-31 14:40:22 +08:00
    贴两篇博客,有时间可以参考下:

    《详解 Python 的 “==” 和 “ is ”》 https://www.kawabangga.com/posts/1673
    《作用还是 Feature ?》 https://www.kawabangga.com/posts/2809
    vimiix
        10
    vimiix  
       2018-03-31 15:27:42 +08:00
    延伸阅读,True,1,1.0 分别作为字典的值的时候会怎样。
    fanhaipeng0403
        12
    fanhaipeng0403  
       2018-03-31 22:34:13 +08:00
    印象中 None null 这样的类型

    不能用=
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2708 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 09:30 · PVG 17:30 · LAX 01:30 · JFK 04:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.