我正在学习和使用Python,我想出了下面的测试代码(请注意,* 我不会写这样的高效代码 *,但在学习新语言时,我喜欢使用该语言的角落案例):
a = None
print(None == a) # I expected True, I got True
b = 1
print(None == b) # I expected False, I got False
class MyNone:
# Called if I compare some myMyNone == somethingElse
def __eq__(self, __o: object) -> bool:
return True
c = MyNone()
print (None == c) # !!! I expected False, I got True !!!
"请看最后一行"
为什么None == something
,其中的东西显然不是None
,返回True
?我希望something == None
的结果是这样的,但None == something
的结果不是这样。
我预计它会在幕后调用None is something
。
所以我认为问题归结为:None
单例对象的__eq__
方法是什么样子的?我是如何发现的?
PS:我知道PEP-0008和它的报价
与单例(如None)的比较应始终使用is或is not,而绝不要使用相等运算符。
但是我 * 仍然 * 想知道为什么上面例子中的print (None == c)
返回True
。
2条答案
按热度按时间f5emj3cl1#
事实上,
None
的类型没有它自己的__eq__
方法;在Python中,我们可以看到它显然继承自基类object
:但是这并不是源代码中真正发生的事情,
None
的实现可以在CPython源代码的Objects/object.c
中找到,我们可以看到:我省略了大部分不相关的部分。这里重要的是
_PyNone_Type
的tp_richcompare
是0
,即一个空指针。这在do_richcompare
函数中检查:为那些不会说C的人翻译:
tp_richcompare
函数不为空,则调用它,如果其结果不是NotImplemented
,则返回该结果。tp_richcompare
函数不为空,则调用它,如果结果不是NotImplemented
,则返回该结果。代码中还有一些其他的分支,如果这些分支都没有返回结果,就可以返回。但这两个分支足以说明发生了什么。这并不是说
type(None).__eq__
返回NotImplemented
,而是该类型在C源代码中根本没有相应的函数。这意味着第二个分支被执行,因此您观察到的结果。checked_reverse_op
;如果右边的是左边的严格子类型,就会发生这种情况,在这种情况下,它具有优先级。但在这种情况下,这并不适用,因为type(None)
和你的类之间没有子类型关系。9jyewag02#
如文件所述:
x==y
调用x.__eq__(y)
,但None.__eq__(...)
为除None
本身之外的任何内容返回NotImplemented
(缺少部分:为什么?我不知道),所以Python尝试了相反的比较,从MyNone
调用__eq__
,MyNone
总是返回True
。更新:
None
(NoneType
类)没有定义自己的__eq__
,而是使用基于is
测试的默认object.__eq__
:如果参数is
相同,则返回True
,否则返回NotImplemented
。