同步阅读进度,多语言翻译,过滤屏幕蓝光,评论分享,更多完整功能,更好读书体验,试试 阅读 ‧ 电子书库
Boolean Tests: __bool__ and __len__
As mentioned earlier, classes may also define methods that give the Boolean nature of their instances—in Boolean contexts, Python first tries __bool__ to obtain a direct Boolean value and then, if that’s missing, tries __len__ to determine a truth value from the object length. The first of these generally uses object state or other information to produce a Boolean result:
>>> class Truth:
... def __bool__(self): return True
...
>>> X = Truth()
>>> if X: print('yes!')
...
yes!
>>> class Truth:
... def __bool__(self): return False
...
>>> X = Truth()
>>> bool(X)
False
If this method is missing, Python falls back on length because a nonempty object is considered true (i.e., a nonzero length is taken to mean the object is true, and a zero length means it is false):
>>> class Truth:
... def __len__(self): return 0
...
>>> X = Truth()
>>> if not X: print('no!')
...
no!
If both methods are present Python prefers __bool__ over __len__, because it is more specific:
>>> class Truth:
... def __bool__(self): return True # 3.0 tries __bool__ first
... def __len__(self): return 0 # 2.6 tries __len__ first
...
>>> X = Truth()
>>> if X: print('yes!')
...
yes!
If neither truth method is defined, the object is vacuously considered true (which has potential implications for metaphysically inclined readers!):
>>> class Truth:
... pass
...
>>> X = Truth()
>>> bool(X)
True
And now that we’ve managed to cross over into the realm of philosophy, let’s move on to look at one last overloading context: object demise.
Booleans in Python 2.6
Python 2.6 users should use __nonzero__ instead of __bool__ in all of the code in the section Boolean Tests: __bool__ and __len__. Python 3.0 renamed the 2.6 __nonzero__ method to __bool__, but Boolean tests work the same otherwise (both 3.0 and 2.6 use __len__ as a fallback).
If you don’t use the 2.6 name, the very first test in this section will work the same for you anyhow, but only because __bool__ is not recognized as a special method name in 2.6, and objects are considered true by default!
To witness this version difference live, you need to return False:
C:\misc> c:\python30\python
>>> class C:
... def __bool__(self):
... print('in bool')
... return False
...
>>> X = C()
>>> bool(X)
in bool
False
>>> if X: print(99)
...
in bool
This works as advertised in 3.0. In 2.6, though, __bool__ is ignored and the object is always considered true:
C:\misc> c:\python26\python
>>> class C:
... def __bool__(self):
... print('in bool')
... return False
...
>>> X = C()
>>> bool(X)
True
>>> if X: print(99)
...
99
In 2.6, use __nonzero__ for Boolean values (or return 0 from the __len__ fallback method to designate false):
C:\misc> c:\python26\python
>>> class C:
... def __nonzero__(self):
... print('in nonzero')
... return False
...
>>> X = C()
>>> bool(X)
in nonzero
False
>>> if X: print(99)
...
in nonzero
But keep in mind that __nonzero__ works in 2.6 only; if used in 3.0 it will be silently ignored and the object will be classified as true by default—just like using __bool__ in 2.6!
请支持我们,让我们可以支付服务器费用。
使用微信支付打赏