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 

在这种情况下, cancelclosedismiss所有引用内存中的同一个对象。 您只创build了一个Button对象,并且所有三个variables都引用这个对象。 我们说cancelclosedismiss都是指相同的对象; 也就是说,他们指的是一个单一的对象。

对象相等 :当你比较两个对象时,你通常不关心它是否指向内存中完全相同的对象。 在对象相等的情况下,您可以为两个对象的比较定义自己的规则。 当你写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, ab 。 他们有完全相同的内容,但他们在记忆中不是同一个对象。 但是,当我们比较它们时,我们希望它们比较相等。 这里发生的是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 

在这里,我有两个戴尔显示器, ab 。 他们有相同的品牌和型号。 但是,它们在内存中既不具有相同的数据,也不具有相同的对象。 但是,当我们比较它们时,我们希望它们比较相等。 这里发生的事情是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
真正

有些对象是单例,因此与它们相当于== 。 大多数不是。