在 Python 2 中,and 和 or 访问 __nonzero__:
>>> class Test(object):
... def __nonzero__(self):
... print '__nonzero__ called'
... return True
...
>>> Test() and 1
__nonzero__ called
1
在 Python 3 中,__nonzero__ 已重命名为 __bool__。
>>> class Test:
... def __bool__(self):
... print('__bool__ called')
... return True
...
>>> Test() and 1
__bool__ called
1
请注意,短路评估可能会抑制对__nonzero__ 或__bool__ 的调用。
>>> 0 and Test()
0
>>> 1 or Test()
1
另一个需要注意的特点是,如果__nonzero__ / __bool__ 未定义,Python 会尝试访问__len__,如果__len__ 返回的值不是0,则将对象视为真实对象。如果两个方法都定义了,__nonzero__ / __bool__ 获胜。
>>> class Test:
... def __len__(self):
... return 23
...
>>> Test() and True
True
>>>
>>> class Test:
... def __len__(self):
... return 23
... def __bool__(self):
... return False
...
>>> Test() and True
<__main__.Test object at 0x7fc18b5e26d8> # evaluation stops at Test() because the object is falsy
>>> bool(Test())
False
有没有什么办法可以让这个返回一个布尔值以外的东西,比如一个布尔值列表?
很遗憾,没有。 documentation 声明该方法应该返回 False 或 True,但实际上如果你让它返回其他东西,你会得到一个 TypeError。
>>> class Test:
... def __bool__(self):
... return 1
...
>>> Test() and 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __bool__ should return bool, returned int
>>>
>>> bool(Test())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __bool__ should return bool, returned int