Python!=操作vs“不是”
在对这个问题的评论中,我看到了一个build议使用的声明
result is not None
VS
result != None
我想知道有什么区别,为什么可以推荐一个呢?
==
是一个平等testing 。 它检查右侧和左侧是否是相等的对象(根据__eq__
或__cmp__
方法)。
是一个身份testing 。 它检查右侧和左侧是否是完全相同的对象。 没有方法调用完成,对象不能影响is
操作。
你使用的is
(而is not
)单例,比如None
,你不关心那些可能想装成None
对象,或者当你与None
进行比较的时候,要防止对象被破坏的地方。
首先,让我讲几句话。 如果您只想回答您的问题,请向下滚动至“回答您的问题”。
定义
对象标识 :创build对象时,可以将其分配给一个variables。 您也可以将其分配给另一个variables。 而另一个。
>>> button = Button() >>> cancel = button >>> close = button >>> dismiss = button >>> print(cancel is close) True
在这种情况下, cancel
, close
和dismiss
所有引用内存中的同一个对象。 您只创build了一个Button
对象,并且所有三个variables都引用这个对象。 我们说cancel
, close
和dismiss
都是指相同的对象; 也就是说,他们指的是一个单一的对象。
对象相等 :当你比较两个对象时,你通常不关心它是否指向内存中完全相同的对象。 在对象相等的情况下,您可以为两个对象的比较定义自己的规则。 当你写if a == b:
,你基本上是说if a.__eq__(b):
这使您可以定义一个__eq__
方法,以便您可以使用自己的比较逻辑。
平等比较的理由
原理:两个物体具有完全相同的数据,但不完全相同。 (它们在内存中不是同一个对象。) 示例:string
>>> greeting = "It's a beautiful day in the neighbourhood." >>> a = unicode(greeting) >>> b = unicode(greeting) >>> a is b False >>> a == b True
注意:我在这里使用unicodestring,因为Python足够聪明,可以重复使用常规string,而无需在内存中创build新string。
在这里,我有两个unicodestring, 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
注意: unicode
上的__eq__
肯定比这更有效。
原理:两个对象具有不同的数据,但是如果某些关键数据相同,则被视为同一个对象。 示例:大多数types的模型数据
>>> 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
。 没有一个是Python中的单例 – 在内存中只有一个实例。
通过比较身份 ,这可以很快执行。 Python会检查你指向的对象是否与全局None对象具有相同的内存地址 – 两个数字的比较非常快。
通过比较平等 ,Python必须查找对象是否有__eq__
方法。 如果没有,它检查每个超类寻找__eq__
方法。 如果find了,Python会调用它。 如果__eq__
方法很慢,并且在注意到另一个对象是None
时不立即返回,则这是特别糟糕的。
你没有实现__eq__
吗? 然后,Python可能会在object
上find__eq__
方法,并使用它 – 它只是检查对象的身份。
当比较Python中的大多数其他事物时,您将使用!=
。
考虑以下几点:
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)
None
一个是单身人士,因此身份比较将始终有效,而对象可以通过.__eq__()
伪造相等比较。
>>>()是() 真正 >>> 1是1 真正 >>>(1,)==(1,) 真正 >>>(1,)是(1,) 假 >>> a =(1,) >>> b = a >>> a是b 真正
有些对象是单例,因此与它们相当于==
。 大多数不是。