documentation明确指出
如果未定义此方法(
__bool__
),则会调用__len__()
(如果已定义),如果对象的结果非零,则认为该对象为true。如果类既未定义__len__()
也未定义__bool__()
,则其所有实例均视为true。
Bold是我的插入,斜体是我的,但文本实际上就在那里。
可以轻松测试类必须包含该方法的事实class A:
pass
a = A()
a.__bool__ = (lamda self: False).__get__(a, type(a))
print(bool(A()), bool(a))
结果是True True
,正如文档所声称的那样。覆盖__len__
会产生相同的结果:
b = A()
b.__len__ = (lambda self: 0).__get__(b, type(b))
print(bool(A()), bool(b))
这与文档声称的完全相同。但是,我发现这背后的推理有点违反直觉。我知道bool
内置函数不会查看实例的方法,但我不明白为什么。知道内部工作原理的人是否知道为什么只有类级别__bool__
和__len__
方法会影响真实性而忽略实例级方法?
答案 0 :(得分:1)
原因是how special methods are looked up。
对于自定义类,只有在对象类型上定义的特殊方法的隐式调用才能保证正常工作,而不是在对象的实例字典中。
...
这种行为背后的基本原理在于许多特殊方法,例如
__hash__()
和__repr__()
,它们由所有对象实现,包括类型对象。如果这些方法的隐式查找使用了传统的查找过程,则在类型对象本身上调用它们时会失败。
...
除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过
__getattribute__()
方法,甚至是对象的元类。
...
以这种方式绕过
__getattribute__()
机制为解释器内的速度优化提供了很大的空间,代价是处理特殊方法的一些灵活性(必须在类对象本身上按顺序设置特殊方法由翻译一致地调用。)