0

文件明确指出

当此方法( __bool__)未定义时__len__(),如果已定义,则调用该方法,如果其结果为非零,则认为该对象为真。如果一个既不定义__len__()也不定义__bool__(),它的所有实例都被认为是真的。

粗体是我的插入,斜体是我的,但文字确实在那里。类必须包含该方法这一事实很容易被测试

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__方法会影响真实性而忽略实例级别的方法?

4

1 回答 1

1

原因是如何查找特殊方法

对于自定义类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。

...

这种行为背后的基本原理在于许多特殊方法,例如__hash__()__repr__()由所有对象实现,包括类型对象。如果这些方法的隐式查找使用传统的查找过程,则在类型对象本身上调用它们时会失败。

...

除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()对象元类的方法。

...

以这种方式绕过__getattribute__()机制为解释器中的速度优化提供了很大的空间,但代价是处理特殊方法的一些灵活性(特殊方法必须在类对象本身上设置,以便解释器始终调用) .

于 2017-02-09T21:01:11.390 回答