预计阅读本页时间:-
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
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
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!