为什么“如果不是某个对象:"比“if someobj == None:"好在 Python 中? [英] Why is "if not someobj:" better than "if someobj == None:" in Python?
问题描述
我见过几个这样的代码示例:
如果不是某个对象:#做一点事
但我想知道为什么不这样做:
if someobj == None:#做一点事
有什么区别吗?一个比另一个有优势吗?
在第一个测试中,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
ifself < other
,0
> ifself == other
,+1
ifself > other
).否则,将比较对象的身份(即,它们是对同一对象的引用,可以通过
is
运算符进行测试).
使用 is
运算符可以进行另一个测试.我们会问这个对象,你是这个特定的对象吗?"
一般来说,我建议对非数字值使用第一个测试,当您想比较相同性质的对象(两个字符串、两个数字……)并检查是否存在相等性时,使用相等性测试仅在使用标记值时标识(例如,None
表示未为成员字段初始化,或者在使用 getattr
或 __getitem__
方法时).
总而言之,我们有:
<预><代码>>>>A类(对象):... def __repr__(self):...返回'A()'... def __nonzero__(self):...返回假>>>B类(对象):... def __repr__(self):...返回'B()'... def __len__(self):...返回0>>>C类(对象):... def __repr__(self):...返回'C()'... def __cmp__(self, other):...返回0>>>D类(对象):... def __repr__(self):...返回'D()'... def __eq__(self, other):...返回真>>>对于 ['', (), [], {}, 0, 0., A(), B(), C(), D(), None] 中的 obj:... 打印 '%4s: bool(obj) ->%5s, obj == 无 ->%5s, obj 是 None ->%5s' % \... (repr(obj), bool(obj), obj == None, obj is None)'': bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的(): bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的[]: bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的{}: bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的0: bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的0.0: bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的A(): bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的B(): bool(obj) ->错误,obj == 无 ->错误,obj 是 None ->错误的C(): bool(obj) ->是的,obj == 无 ->是的,obj 是 None ->错误的D(): bool(obj) ->是的,obj == 无 ->是的,obj 是 None ->错误的无:bool(obj) ->错误,obj == 无 ->是的,obj 是 None ->真的I've seen several examples of code like this:
if not someobj:
#do something
But I'm wondering why not doing:
if someobj == None:
#do something
Is there any difference? Does one have an advantage over the other?
In the first test, Python try to convert the object to a bool
value if it is not already one. Roughly, we are asking the object : are you meaningful or not ? This is done using the following algorithm :
If the object has a
__nonzero__
special method (as do numeric built-ins,int
andfloat
), it calls this method. It must either return abool
value which is then directly used, or anint
value that is consideredFalse
if equal to zero.Otherwise, if the object has a
__len__
special method (as do container built-ins,list
,dict
,set
,tuple
, ...), it calls this method, considering a containerFalse
if it is empty (length is zero).Otherwise, the object is considered
True
unless it isNone
in which case, it is consideredFalse
.
In the second test, the object is compared for equality to None
. Here, we are asking the object, "Are you equal to this other value?" This is done using the following algorithm :
If the object has a
__eq__
method, it is called, and the return value is then converted to abool
value and used to determine the outcome of theif
.Otherwise, if the object has a
__cmp__
method, it is called. This function must return anint
indicating the order of the two object (-1
ifself < other
,0
ifself == other
,+1
ifself > other
).Otherwise, the object are compared for identity (ie. they are reference to the same object, as can be tested by the
is
operator).
There is another test possible using the is
operator. We would be asking the object, "Are you this particular object?"
Generally, I would recommend to use the first test with non-numerical values, to use the test for equality when you want to compare objects of the same nature (two strings, two numbers, ...) and to check for identity only when using sentinel values (None
meaning not initialized for a member field for exemple, or when using the getattr
or the __getitem__
methods).
To summarize, we have :
>>> 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
这篇关于为什么“如果不是某个对象:"比“if someobj == None:"好在 Python 中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!