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 withis
or
is not
, never the equality operators.
总之,对于像None这样的单例,使用is的引用检查更合适,尽管两者都是==并且可以正常工作.
标签:boolean-expression,python,python-3-x,string,equivalence 来源: https://codeday.me/bug/20191003/1850750.html