编程语言
首页 > 编程语言> > python – 为什么`if None .__ eq __(“a”)`似乎评估为True(但不完全)?

python – 为什么`if None .__ eq __(“a”)`似乎评估为True(但不完全)?

作者:互联网

如果在Python 3.7中执行以下语句,它将(从我的测试中)打印b:

if None.__eq__("a"):
    print("b")

但是,None .__ eq __(“a”)的计算结果为NotImplemented.

当然,“a”.__ eq __(“a”)的计算结果为True,而“b”.__ eq __(“a”)的计算结果为False.

我最初在测试函数的返回值时发现了这一点,但在第二种情况下没有返回任何内容 – 因此,函数返回None.

这里发生了什么?

解决方法:

这是为什么不应该直接使用__dunder__方法的一个很好的例子,因为它们通常不适合替代它们的等效运算符;你应该使用==运算符来进行相等比较,或者在这种特殊情况下,当检查None时,使用is(跳到答案的底部以获取更多信息).

你做完了

None.__eq__('a')
# NotImplemented

由于被比较的类型不同,因此返回NotImplemented.考虑另一个例子,其中以这种方式比较具有不同类型的两个对象,例如1和’a’.执行(1).__ eq __(‘a’)也不正确,并将返回NotImplemented.将这两个值进行比较的正确方法是

1 == 'a'
# False

这里发生的是

>首先,尝试(1).__ eq __(‘a’),返回NotImplemented.这表示不支持该操作,因此
>’a’.__ eq __(1)被调用,它也返回相同的NotImplemented.所以,
>对象被视为不相同,并返回False.

这是一个很好的小MCVE使用一些自定义类来说明这是如何发生的:

class A:
    def __eq__(self, other):
        print('A.__eq__')
        return NotImplemented

class B:
    def __eq__(self, other):
        print('B.__eq__')
        return NotImplemented

class C:
    def __eq__(self, other):
        print('C.__eq__')
        return True

a = A()
b = B()
c = C()

print(a == b)
# A.__eq__
# B.__eq__
# False

print(a == c)
# A.__eq__
# C.__eq__
# True

print(c == a)
# C.__eq__
# True

当然,这并不能解释为什么操作返回true.这是因为NotImplemented实际上是一个真正的价值:

bool(None.__eq__("a"))
# True

如同,

bool(NotImplemented)
# True

有关什么值被认为是真实和虚假的更多信息,请参阅Truth Value Testing以及this answer的文档部分.值得注意的是,NotImplemented是真实的,但如果类定义了__bool__或__len__,那将是一个不同的故事.返回False或0的方法.

如果要使用==运算符的功能等效项,请使用operator.eq

import operator
operator.eq(1, 'a')
# False

但是,如前所述,对于此特定方案,您要检查None,请使用:

var = 'a'
var is None
# False

var2 = None
var2 is None
# True

功能等同于使用operator.is_

operator.is_(var2, None)
# True

None是一个特殊对象,在任何时间点内存中只有1个版本. IOW,它是NoneType类的唯一单例(但同一个对象可能有任意数量的引用). PEP8 guidelines明确指出:

Comparisons to singletons like None should always be done with is or
is not, never the equality operators.

总之,对于像None这样的单例,使用is的引用检查更合适,尽管两者都是==并且可以正常工作.

标签:boolean-expression,python,python-3-x,string,equivalence
来源: https://codeday.me/bug/20191003/1850750.html