“foo is None”和“foo == None”之间有啥区别吗?

Posted

技术标签:

【中文标题】“foo is None”和“foo == None”之间有啥区别吗?【英文标题】:Is there any difference between "foo is None" and "foo == None"?“foo is None”和“foo == None”之间有什么区别吗? 【发布时间】:2010-09-06 19:07:22 【问题描述】:

两者有什么区别:

if foo is None: pass

if foo == None: pass

我在大多数 Python 代码(以及我自己编写的代码)中看到的约定是前者,但我最近遇到了使用后者的代码。 None 是 NoneType 的一个实例(也是唯一的实例,IIRC),所以没关系,对吧?有没有什么情况下可能?

【问题讨论】:

这能回答你的问题吗? What is the difference between "is None" and "== None" 【参考方案1】:

is 在比较同一个对象实例时总是返回True

== 最终由__eq__() 方法确定


>>> class Foo(object):
       def __eq__(self, other):
           return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False

【讨论】:

您可能需要添加 None 是单例,因此“None is None”始终为 True。 您可能还想补充一点,is 运算符不能自定义(被用户定义的类重载)。 @study __eq__(self) 方法是一个特殊的内置方法,用于确定在 Python 对象上使用时如何处理 ==。这里我们重写了它,所以当== 用于Foo 类型的对象时,它总是返回true。 is 运算符没有等效的方法,因此 is 的行为不能以相同的方式更改。 是不是因为foo类的定义没有构造函数,即init函数?【参考方案2】:

您可能想阅读此object identity and equivalence。

语句'is'用于对象标识,它检查对象是否引用相同的实例(内存中的相同地址)。

而 '==' 语句指的是相等(相同的值)。

【讨论】:

嗯,我认为您的链接已更改,除非您对如何从 python 调用外部函数感兴趣 我刚试过a=1;b=1;print(a is b) # True。知道为什么a is b 是真的,即使它们似乎是 2 个不同的对象(内存中的不同地址)?【参考方案3】:

请注意:

if foo:
  # do something

完全等同于:

if x is not None:
  # do something

前者是一个布尔值测试,可以在不同的上下文中评估为 false。在布尔值测试中,有很多东西代表错误,例如空容器、布尔值。在这种情况下,None 的计算结果也为 false,但其他情况也一样。

【讨论】:

【参考方案4】:

(ob1 is ob2) 等于 (id(ob1) == id(ob2))

【讨论】:

... 但是(ob 是 ob2)要快很多。 Timeit 说“(a is b)”是每个循环 0.0365 微秒,“(id(a)==id(b))”是每个循环 0.153 微秒。快 4.2 倍! is 版本不需要函数调用,也不需要 python-interpreter 属性查找;如果 ob1 实际上是 ob2,解释器可以立即回答。 不,它没有。 is 是假的,id() == id() 可以是(在 CPython 中 )真。见***.com/questions/3877230【参考方案5】:

foo is None 是首选方式的原因是您可能正在处理一个定义了自己的__eq__ 的对象,并且该对象将对象定义为等于无。所以,如果你需要查看它是否是None,请始终使用foo is None

【讨论】:

【参考方案6】:

没有区别,因为相同的对象当然是相等的。但是,PEP 8 明确指出您应该使用is

与 None 等单例的比较应始终使用 is 或 not,而不是相等运算符。

【讨论】:

【参考方案7】:

is 测试身份,相等。对于您的声明foo is none,Python 只是比较对象的内存地址。这意味着您在问“我对同一个对象有两个名称吗?”

另一方面,== 测试由__eq__() 方法确定的相等性。它不关心身份。

In [102]: x, y, z = 2, 2, 2.0

In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)

In [104]: x is y
Out[104]: True

In [105]: x == y
Out[105]: True

In [106]: x is z
Out[106]: False

In [107]: x == z
Out[107]: True

None 是一个单例运算符。所以None is None 总是正确的。

In [101]: None is None
Out[101]: True

【讨论】:

【参考方案8】:

对于 None,等式 (==) 和身份 (is) 之间不应有区别。 NoneType 可能返回相等的身份。由于 None 是唯一可以使用 NoneType 的实例(我认为这是真的),因此这两个操作是相同的。在其他类型的情况下,情况并非总是如此。例如:

list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"

这将打印“Equal”,因为列表有一个不是默认返回标识的比较操作。

【讨论】:

【参考方案9】:

@Jason:

我建议使用更多类似的东西

if foo:
    #foo isn't None
else:
    #foo is None

我不喜欢使用“if foo:”,除非 foo 真正代表一个布尔值(即 0 或 1)。如果 foo 是一个字符串或一个对象或其他东西,“if foo:”可能会起作用,但它对我来说似乎是一个懒惰的捷径。如果您正在检查 x 是否为 None,请说“如果 x 为 None:”。

【讨论】:

使用“if var”检查空字符串/列表是首选方法。布尔转换定义明确,代码更少,性能更好。例如,没有理由做“if len(mylist) == 0”。 错了。假设 foo = ""。那么if foo会返回false,评论#foo is None是错误的。 请注意 - 我的回答是引用一个已被删除并不同意的答案。如果你喜欢我回答中的代码,你需要upvote。 :-)【参考方案10】:

更多细节:

    is 子句实际上检查两个objects 是否相同 内存位置与否。即它们是否都指向同一个 内存位置并具有相同的id

    作为 1 的结果,is 确保两个词法表示的objects 是否具有相同的属性(attributes-of-attributes...)

    李>

    基元类型的实例化,如boolintstring(有一些例外)、NoneType,具有相同的值将始终位于相同的内存位置。

    李>

例如

>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True

而且由于NoneType 在 python 的“查找”表中只能有一个自身实例,因此前者和后者更像是编写代码的开发人员的一种编程风格(可能是为了保持一致性)而不是有任何微妙的逻辑理由来选择一个而不是另一个。

【讨论】:

阅读本文的每个人:永远不要使用some_string is "bar" 来比较字符串。没有一个可以接受的理由这样做,并且当您不期望它时它会中断。它经常工作的事实仅仅是因为 CPython 知道创建两个具有相同内容的不可变对象是愚蠢的。但它仍然可能发生。 @ThiefMaster 答案是否有被误解的倾向?不过,在再次阅读时 找不到它(提到“一些例外”)。您的声明仅适用于字符串,而不适用于 int,对吗? 不是真的,但是由于您的答案中有该示例,我认为警告用户实际使用它是一个坏主意是个好主意。也许在该行后面添加诸如“# cpython specific / notGuaranteed”之类的内容......【参考方案11】:

John Machin 关于None 是单例的结论是由这段代码支持的结论。

>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>> 

由于None 是单例,x == Nonex is None 将具有相同的结果。但是,在我看来,x == None 是最好的。

【讨论】:

我不同意这个答案末尾的观点。当与 none 显式比较时,通常意味着所讨论的对象正是 None 对象。相比之下,除了与False 相似且其他值为真值外,很少有人在任何其他上下文中看到 None 。在这些情况下,做类似if x: pass 之类的事情会更惯用【参考方案12】:
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence 


a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True

【讨论】:

以上是关于“foo is None”和“foo == None”之间有啥区别吗?的主要内容,如果未能解决你的问题,请参考以下文章

& 和 && 区别和联系,| 和 || 区别和联系

第三十一节:扫盲并发和并行同步和异步进程和线程阻塞和非阻塞响应和吞吐等

shell中$()和 ` `${}${!}${#}$[] 和$(()),[ ] 和(( ))和 [[ ]]

Java基础8---面向对象代码块和继承和this和super和重写和重载和final

Java基础8---面向对象代码块和继承和this和super和重写和重载和final

JS中some()和every()和join()和concat()和pop(),push(),shift(),unshfit()和map()和filter()