关于python:“ foo is None”和“ foo == None”之间是否有区别?

关于python:“ foo is None”和“ foo == None”之间是否有区别?

Is there any difference between “foo is None” and “foo == None”?

之间有什么区别:

1
if foo is None: pass

1
if foo == None: pass

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


如果is比较相同的对象实例,则始终返回True

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

1
2
3
4
5
6
7
8
9
>>> class Foo(object):
       def __eq__(self, other):
           return True

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

您可能需要阅读此对象的标识和等效信息。

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

并且'=='语句引用相等(相同值)。


请注意:

1
2
if foo:
  # do something

与以下内容不完全相同:

1
2
if x is not None:
  # do something

前者是布尔值测试,可以在不同的上下文中评估为false。在布尔值测试中,有很多东西代表假,例如空容器,布尔值。在这种情况下,没有人会得出错误的结论,但其他事情也会发生。


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


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


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

Comparisons to singletons like None should always be done with is or is not, never the equality operators.


is测试身份,而不是相等性。对于您的语句foo is None,Python只是比较对象的内存地址。这意味着您要问的问题是"同一对象有两个名称吗?"

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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始终为true。

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

@Jason:

I recommend using something more along the lines of

1
2
3
4
if foo:
    #foo isn't None
else:
    #foo is None

我不喜欢使用" if foo:",除非foo真正表示一个布尔值(即0或1)。如果foo是字符串或对象或其他对象,则" if foo:"可能有效,但对我来说似乎是个懒惰的快捷方式。如果要检查x是否为None,请说"如果x为None:"。


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

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

这将打印"等于",因为列表具有比较操作,而不是默认返回标识。


一些更多的细节:

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

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

  • 具有相同值的boolintstring(NoneType),NoneType等原始类型的实例化将始终位于相同的存储位置。

  • 例如。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    >>> 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的"查找"表中只能有一个实例本身,因此前者和后者更像是编写代码的开发人员的编程风格(也许是为了保持一致性),而不是具有任何细微之处。选择一个而不是另一个的逻辑原因。


    John Machin关于None是单例的结论是受此代码支持的结论。

    1
    2
    3
    4
    5
    6
    7
    >>> x = None
    >>> y = None
    >>> x == y
    True
    >>> x is y
    True
    >>>

    由于None是单例,因此x == Nonex is None将具有相同的结果。但是,从我的美学观点来看,x == None是最好的。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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


    推荐阅读