这是一个很好的例子,说明为什么__dunder__
不应该直接使用这些方法,因为它们通常不是等效操作符的适当替代;您应该使用==
运算符来代替相等性比较,或者在这种特殊情况下,当检查时None
,请使用is
(跳至答案的底部以获取更多信息)。
你做完了
None.__eq__('a')
# NotImplemented
NotImplemented
由于要比较的类型不同,返回的结果不同。考虑另一个示例,其中以这种方式比较了具有不同类型的两个对象,例如1
和'a'
。这样做(1).__eq__('a')
也不正确,并且会返回NotImplemented
。比较这两个值是否相等的正确方法是
1 == 'a'
# 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
当然,这并不能解释 @H_403_60@为什么 该操作返回true。这是因为NotImplemented
实际上是一个真实值:
bool(None.__eq__("a"))
# True
和…一样,
bool(NotImplemented)
# True
有关什么值被认为是真实和虚假的更多信息,请参阅真值测试的文档部分以及此答案。值得注意的是,这里NotImplemented
是truthy,但它会是一个不同的故事有类中定义一个__bool__
或__len__
方法返回False
或0
分别。
如果要==
使用与运算符等效的功能,请使用operator.eq
:
import operator
operator.eq(1, 'a')
# False
但是,如前所述,对于要检查的 @H_403_60@特定情况 ,请None
使用is
:
var = 'a'
var is None
# False
var2 = None
var2 is None
# True
其功能等效项是使用operator.is_
:
operator.is_(var2, None)
# True
None
是一个特殊对象,并且在任何时间内存中只有1个版本。IOW,它是类的唯一单例nonetype
(但是同一对象可以具有任意数量的引用)。该PEP8方针更加明确:
与单例之类的比较None
应始终使用is
或 is not
,而不应使用相等运算符。
综上所述,对于单身人士喜欢None
,与基准检查is
是比较合适的,虽然两者==
并is
会工作得很好。