在第一个测试中,Python 尝试将对象转换为 bool 值(如果它还不是一个值)。粗略地说,我们在问对象:你有意义吗?这是使用以下算法完成的:
如果对象具有__nonzero__ 特殊方法(如数字内置函数int 和float),它会调用此方法。它必须要么返回一个 bool 值,然后直接使用,要么返回一个 int 值,如果等于 0,则被视为 False。
否则,如果对象具有__len__ 特殊方法(如容器内置,list,dict,set,tuple,...),它调用这个方法,考虑容器False,如果它是空的(长度为零)。
否则,对象被视为True,除非它是None,在这种情况下,它被视为False。
在第二个测试中,比较对象与None 的相等性。在这里,我们询问对象,“你是否等于这个其他值?”这是使用以下算法完成的:
-
如果对象具有__eq__方法,则调用该方法,然后将返回值转换为bool值并用于确定if的结果。
否则,如果对象有__cmp__ 方法,则调用它。这个函数必须返回一个int,表示两个对象的顺序(-1如果self < other,0如果self == other,+1如果self > other)。
否则,将比较对象的身份(即它们引用同一对象,可以通过is 运算符进行测试)。
使用is 运算符可以进行另一个测试。 我们会问对象,“你是这个特定的对象吗?”
一般来说,我建议使用非数值的第一个测试,当您想要比较相同性质的对象(两个字符串,两个数字,...)时使用相等性测试并检查仅在使用标记值时标识(例如,None 表示未为成员字段初始化,或者在使用 getattr 或 __getitem__ 方法时)。
总而言之,我们有:
>>> 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