【问题标题】: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),所以没关系,对吧?有没有什么情况下可能?

【问题讨论】:

标签: python


【解决方案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 中 )真。见stackoverflow.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】:

            更多细节:

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

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

              李>
            3. 基元类型的实例化,如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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-09-09
              • 1970-01-01
              • 2010-12-12
              • 1970-01-01
              • 1970-01-01
              • 2012-08-08
              • 2016-12-01
              相关资源
              最近更新 更多