Python!=操作vs“不是”

时间:2010-02-05 19:21:46

标签: python operators

在对this question的评论中,我看到了一条建议使用

的声明
result is not None

VS

result != None

我想知道区别是什么,以及为什么可能推荐另一个?

5 个答案:

答案 0 :(得分:249)

==相等测试。它检查右手侧和左手侧是否是相同的对象(根据他们的__eq____cmp__方法。)

is身份测试。它检查右手侧和左手侧是否是同一个物体。没有方法调用,对象不能影响is操作。

您使用is(和is not)作为单身人士,例如None,您不关心可能想要假装为None的对象或其他地方您希望在与None进行比较时防止对象中断。

答案 1 :(得分:127)

首先,让我谈谈几个条款。如果您只想回答问题,请向下滚动到“回答您的问题”。

解释

对象标识:创建对象时,可以将其分配给变量。然后,您还可以将其分配给另一个变量。而另一个。

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

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

对象相等性:比较两个对象时,通常不关心它是否指向内存中的 exact 相同对象。通过对象相等,您可以为两个对象的比较定义自己的规则。当您撰写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字符串,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

注意:__eq__上的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

在这里,我有两台戴尔监视器,ab。他们有相同的品牌和型号。但是,它们既没有相同的数据,也没有相同的内存对象。但是,当我们比较它们时,我们希望它们相等。这里发生的是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对象具有相同的内存地址 - 这是对两个数字进行非常非常快速的比较。

通过比较 equality ,Python必须查找您的对象是否具有__eq__方法。如果没有,它会检查每个超类,寻找__eq__方法。如果找到一个,Python会调用它。如果__eq__方法很慢并且当它注意到另一个对象是None时没有立即返回,那么这尤其糟糕。

您没有实施__eq__吗?然后Python可能会在__eq__上找到object方法,而是使用它 - 它只是检查对象身份。

在比较Python中的大多数其他内容时,您将使用!=

答案 2 :(得分:24)

请考虑以下事项:

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)

答案 3 :(得分:15)

None是单身,因此身份比较将始终有效,而对象可以通过.__eq__()伪造相等比较。

答案 4 :(得分:7)

>>> () is ()
True
>>> 1 is 1
True
>>> (1,) == (1,)
True
>>> (1,) is (1,)
False
>>> a = (1,)
>>> b = a
>>> a is b
True

有些对象是单例,因此is与它们等同于==。大多数都没有。