Why is “if not someobj:” better than “if someobj == None:” in Python?
我看到过一些这样的代码示例:
1 2 | if not someobj: #do something |
但我想知道为什么不做:
1 2 | if someobj == None: #do something |
有什么区别吗?一个比另一个有优势吗?
在第一个测试中,python尝试将对象转换为一个
如果对象有一个
否则,如果对象有一个
否则,对象被认为是
在第二个测试中,比较对象是否与
如果对象具有
否则,如果对象具有
否则,对对象进行身份比较(即,它们引用同一对象,可以由
使用
一般来说,我建议使用第一个具有非数值的测试,当您想比较具有相同性质的对象(两个字符串、两个数字等)时使用相等性测试,并且仅当使用sentinel值(例如,
总而言之,我们有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | >>> 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 |
这实际上都是不好的做法。从前,人们认为随意地对待"无"和"假"是可以的。但是,由于python 2.2,这不是最好的策略。
首先,当您执行
在python 2.2之前,没有bool函数,所以更不清楚。
第二,你不应该真的用
参见PEP8,python代码的样式指南。
1
2
3
4
5
6
7 - Comparisons to singletons like None should always be done with
'is' or 'is not', never the equality operators.
Also, beware of writing"if x" when you really mean"if x is not None"
-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value. The other value might have a type
(such as a container) that could be false in a boolean context!
有多少个单件?五:
因为不是只有
1 2 3 4 5 6 7 8 9 10 11 12 | if not False: print"False is false." if not 0: print"0 is false." if not []: print"An empty list is false." if not (): print"An empty tuple is false." if not {}: print"An empty dict is false." if not"": print"An empty string is false." |
此外,考虑以下内容:
1 2 3 4 | >>> False == 0 True >>> False == () False |
这就是短路表达式背后的"魔力",比如:
1 | foo = bar and spam or eggs |
以下简称:
1 2 3 4 | if bar: foo = spam else: foo = eggs |
尽管你真的应该写:
1 | foo = spam if bar else egg |
如果你问
1 2 | if not spam: print"Sorry. No SPAM." |
调用垃圾邮件的非零方法。从python手册:
__nonzero__(self)
Called to implement truth value testing, and the built-in operation bool(); should return False or True, or their integer equivalents 0 or 1. When this method is not defined, __len__() is called, if it is defined (see below). If a class defines neither __len__() nor __nonzero__(), all its instances are considered true.
如果你问
1 2 | if spam == None: print"Sorry. No SPAM here either." |
使用参数none调用垃圾邮件的 eq 方法。
有关定制的更多信息,请访问https://docs.python.org/reference/datamodel.html basic customization查看python文档。
PEP8——python代码的样式指南建议在测试none时使用is或is。
1
2 - Comparisons to singletons like None should always be done with
'is' or 'is not', never the equality operators.
另一方面,如果您测试的是非,那么应该使用布尔运算符。
这两个比较有不同的目的。前者检查某物的布尔值,后者检查无值的标识。
就我个人而言,我选择了跨语言的一致方法:只有当var声明为布尔值(或在C中定义为布尔值,我们没有特定类型)时,我才使用EDOCX1(或等效值)。我甚至在这些变量前面加上了一个
当然,人们会不同意。有些人走得更远,在我的Java代码中,我看到EDOCX1 50(太多余了!)其他人喜欢过多紧凑的语法,使用
答案是"视情况而定"。
如果我认为0,",[]和false(list不是详尽的)在这个上下文中等同于none,那么使用第一个示例。
首先,第一个例子更短,看起来更好。与其他文章一样,你选择什么也取决于你真正想用比较做什么。