Python!=操作vs"不是"

vik*_*sit 223 python operators

在对这个问题的评论中,我看到了一个建议使用的声明

result is not None
Run Code Online (Sandbox Code Playgroud)

VS

result != None
Run Code Online (Sandbox Code Playgroud)

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

Tho*_*ers 273

==是一个平等测试.它检查右手侧和左手侧是否是相同的物体(根据他们__eq____cmp__方法).

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

您可以使用is(和is not)单例,例如None,您不关心可能想要伪装的对象,None或者在进行比较时希望防止对象破坏的对象None.

  • 我最喜欢理解的方法是:Python的`is`就像Java的`==`.Python的`==`就像Java的`.equals()`.当然,只有了解Java才有用. (27认同)
  • @MatrixFrog:在PHP或JavaScript中我们会说`is`就像`===`(非常相等),相反``is`就像``==`(不完全相等). (4认同)
  • 谢谢你的答案 - 你能详细说明一个物体可以破碎的情况,与无比的情况进行比较吗? (3认同)
  • @viksit.`None`有很少的方法,几乎​​没有属性.如果你的`__eq__`测试需要一个方法或属性,它可能会破坏.`def __eq __(self,other):return self.size == other.size`.例如,如果`other`恰好是'None`,则会中断. (3认同)
  • "不是"是一个单独的操作符还是只是在内部否定"是"的结果,就像"不是foo就是吧"一样? (3认同)

Wes*_*ley 133

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

定义

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

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
Run Code Online (Sandbox Code Playgroud)

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

对象相等性:比较两个对象时,通常不关心它是否指向内存中完全相同的对象.通过对象相等,您可以为两个对象的比较定义自己的规则.当你写作时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
Run Code Online (Sandbox Code Playgroud)

注意:我在这里使用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
Run Code Online (Sandbox Code Playgroud)

注意:__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
Run Code Online (Sandbox Code Playgroud)

在这里,我有两台戴尔显示器,ab.他们有相同的品牌和型号.但是,它们既没有相同的数据,也没有相同的内存对象.但是,当我们比较它们时,我们希望它们相等.这里发生的是Monitor对象实现了该__eq__方法.

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model
Run Code Online (Sandbox Code Playgroud)

回答你的问题

比较时None,总是使用is not.None是Python中的单例 - 在内存中只有一个实例.

通过比较身份,可以非常快速地执行.Python检查您所引用的对象是否与全局None对象具有相同的内存地址 - 两个数字的非常非常快速的比较.

通过比较相等性,Python必须查找对象是否有__eq__方法.如果没有,它会检查每个超类寻找__eq__方法.如果找到一个,Python会调用它.如果__eq__方法很慢并且在注意到另一个对象时不立即返回,则这尤其不好None.

你没有实施__eq__吗?然后Python可能会找到该__eq__方法object并使用它 - 无论如何它只是检查对象身份.

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


Alo*_*hal 28

考虑以下:

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)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常有用且简单的示例。谢谢你。 (2认同)

Ign*_*ams 16

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

  • 我没有反对伪造"无"的平等的理由,但是关于"无"的不正确行为可能会发生作为实现与其他类型的平等的副作用.它不仅仅是安全隐患,而是正确性含义. (2认同)

eph*_*ent 7

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

有些物体是单体,因此is与它们相当==.大多数不是.

  • 其中大部分仅按巧合/实施细节进行.`()`和`1`本身并不是单身人士. (4认同)
  • 它是如何实施的,但它没有意义,有用或有教育意义. (3认同)