Python != 操作与“不是”
- 2025-02-14 09:50:00
- admin 原创
- 46
问题描述:
在对这个问题的评论中,我看到一个建议使用
result is not None
对比
result != None
有什么区别?为什么其中一个更受推荐?
解决方案 1:
==
是一个相等性测试。它检查右侧和左侧是否是相等的对象(根据它们的__eq__
或__cmp__
方法)。
is
是身份测试。它检查右侧和左侧是否是同一个对象。没有进行任何方法调用,对象无法影响操作is
。
您可以使用is
(和is not
) 来表示单例,例如None
,当您不关心可能想要假装的对象时None
,或者当您想要防止对象在与 进行比较时被破坏时None
。
解决方案 2:
首先,让我介绍几个术语。如果您只想得到问题的答案,请向下滚动到“回答您的问题”。
定义
对象身份:当你创建一个对象时,你可以将它分配给一个变量。然后你也可以将它分配给另一个变量。等等。
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
在这种情况下,cancel
、close
和dismiss
all 引用内存中的同一个对象。您只创建了一个Button
对象,所有三个变量都引用这个对象。我们说cancel
、close
和dismiss
all 引用相同的对象;也就是说,它们引用一个对象。
对象相等性:比较两个对象时,通常不会关心它们是否引用内存中的同一个对象。使用对象相等性,您可以定义自己的规则来比较两个对象。当您编写 时if a == b:
,您实际上是在说if a.__eq__(b):
。这允许您定义一个__eq__
方法,a
以便您可以使用自己的比较逻辑。
平等比较的基本原理
原理:两个对象拥有完全相同的数据,但并不相同。(它们不是内存中的同一个对象。)
示例:字符串
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
注意:我在这里使用 unicode 字符串,因为 Python 足够智能,可以重用常规字符串,而无需在内存中创建新的字符串。
这里,我有两个 unicode 字符串,a
和b
。它们具有完全相同的内容,但它们在内存中不是同一个对象。但是,当我们比较它们时,我们希望它们相等。这里发生的事情是 unicode 对象已经实现了该__eq__
方法。
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in zip(self, other):
if i != j:
return False
return True
注意:__eq__
on 的unicode
实现肯定比这个更有效率。
原理:两个对象有不同的数据,但如果某些关键数据相同,则被视为同一对象。
示例:大多数类型的模型数据
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
这里,我有两台戴尔显示器a
和b
。它们的品牌和型号相同。但是,它们既没有相同的数据,也不是内存中的相同对象。但是,当我们比较它们时,我们希望它们相等。这里发生的事情是 Monitor 对象实现了该__eq__
方法。
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
回答你的问题
与 进行比较时None
,始终使用is not
。 None 在 Python 中是单例 - 内存中只有一个实例。
通过比较身份,这可以非常快速地完成。Python 检查您引用的对象是否具有与全局 None 对象相同的内存地址 - 非常非常快速地比较两个数字。
通过比较相等性,Python 必须查找对象是否有__eq__
方法。如果没有,它会检查每个超类以查找方法。如果找到一个,Python 就会调用它。如果方法很慢并且在注意到另一个对象是时没有立即返回,__eq__
这种情况尤其糟糕。__eq__
`None`
你没有实现吗__eq__
?那么 Python 可能会找到该__eq__
方法object
并改用该方法 - 无论如何它只是检查对象身份。
当与 Python 中的大多数其他事物进行比较时,您将使用!=
。
解决方案 3:
请考虑以下情况:
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
解决方案 4:
None
是单例,因此身份比较总是有效的,而对象可以通过伪造相等性比较来做到这一点.__eq__()
。
解决方案 5:
>>> () 是 ()
真的
>>> 1 是 1
真的
>>> (1,)==(1,)
真的
>>> (1,)是(1,)
错误的
>>> a = (1,)
>>> b = a
>>> a 是 b
真的
有些对象是单例的,因此is
与它们等同于==
。大多数不是。