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!