<p>在第一个测试中,Python尝试将对象转换为一个<code>bool</code>值(如果它还不是一个值)。粗略地说,<strong>我们问的是:你有没有意义?</strong>这是使用以下算法完成的:</p>
<ol>
<li><p>如果对象有一个<code>__nonzero__</code>特殊方法(就像数字内置的<code>int</code>和<code>float</code>),它将调用此方法。它必须返回一个随后直接使用的<code>bool</code>值,或者如果等于零,则返回一个被视为<code>int</code>值。</p></li>
<li><p>否则,如果对象有一个<code>__len__</code>特殊方法(容器内置的<code>list</code>,<code>dict</code>,<code>set</code>,<code>tuple</code>,…),则调用此方法,如果该方法为空(长度为零),则考虑容器<code>False</code>。</p></li>
<li><p>否则,对象被认为是<code>True</code>,除非它是<code>None</code>,在这种情况下,它被认为是<code>False</code>。</p></li>
</ol>
<p>在第二个测试中,比较对象是否与<code>None</code>相等。在这里,<strong>我们问这个对象,“你是否等于另一个值?”</strong>这是使用以下算法完成的:</p>
<ol>
<li><p>如果对象具有<code>__eq__</code>方法,则调用该方法,然后将返回值转换为<code>bool</code>值,并用于确定<code>if</code>的结果。</p></li>
<li><p>否则,如果对象有一个<code>__cmp__</code>方法,则调用它。此函数必须返回一个<code>int</code>,指示两个对象的顺序(<code>-1</code>如果<code>self < other</code>,<code>0</code>如果<code>self == other</code>,<code>+1</code>如果<code>self > other</code>)。</p></li>
<li><p>否则,将比较对象的标识(即它们是对同一对象的引用,可以通过<code>is</code>运算符进行测试)。</p></li>
</ol>
<p>可以使用<code>is</code>运算符进行另一个测试。<strong>我们会问对象,“你是这个特定对象吗?”</strong></p>
<p>一般来说,我建议对非数值使用第一个测试,当您要比较相同性质的对象(两个字符串、两个数字,…)时使用相等测试,并且仅当使用sentinel值时才检查标识(例如,<code>None</code>表示没有为成员字段初始化,或者当使用<code>getattr</code>或<code>__getitem__</code>方法时)。</p>
<p>总而言之,我们有:</p>
<pre><code>>>> class A(object):
... def __repr__(self):
... return 'A()'
... def __nonzero__(self):
... return False
>>> class B(object):
... def __repr__(self):
... return 'B()'
... def __len__(self):
... return 0
>>> class C(object):
... def __repr__(self):
... return 'C()'
... def __cmp__(self, other):
... return 0
>>> class D(object):
... def __repr__(self):
... return 'D()'
... def __eq__(self, other):
... return True
>>> for obj in ['', (), [], {}, 0, 0., A(), B(), C(), D(), None]:
... print '%4s: bool(obj) -> %5s, obj == None -> %5s, obj is None -> %5s' % \
... (repr(obj), bool(obj), obj == None, obj is None)
'': bool(obj) -> False, obj == None -> False, obj is None -> False
(): bool(obj) -> False, obj == None -> False, obj is None -> False
[]: bool(obj) -> False, obj == None -> False, obj is None -> False
{}: bool(obj) -> False, obj == None -> False, obj is None -> False
0: bool(obj) -> False, obj == None -> False, obj is None -> False
0.0: bool(obj) -> False, obj == None -> False, obj is None -> False
A(): bool(obj) -> False, obj == None -> False, obj is None -> False
B(): bool(obj) -> False, obj == None -> False, obj is None -> False
C(): bool(obj) -> True, obj == None -> True, obj is None -> False
D(): bool(obj) -> True, obj == None -> True, obj is None -> False
None: bool(obj) -> False, obj == None -> True, obj is None -> True
</code></pre>