当前位置:  开发笔记 > 编程语言 > 正文

为什么"if not someobj:"比Python中的"if someobj == None:"更好?

如何解决《为什么"ifnotsomeobj:"比Python中的"ifsomeobj==None:"更好?》经验,为你挑选了3个好方法。

我见过几个像这样的代码示例:

if not someobj:
    #do something

但我想知道为什么不这样做:

if someobj == None:
    #do something

有什么区别吗?一个人比另一个人有优势吗?



1> Sylvain Defr..:

在第一个测试中,Python尝试将对象转换为bool值,如果它不是一个值.大致,我们问的对象是:你有意义吗?这是使用以下算法完成的:

    如果对象有一个__nonzero__特殊的方法(如做数字内置插件,intfloat),它会调用这个方法.它必须要么返回一个bool直接使用的int值,或者False如果等于零则值.

    否则,如果对象有一个__len__特殊的方法(如做容器内置插件,list,dict,set,tuple,...),它会调用这个方法,考虑一个容器False,如果它是空的(长度为零).

    否则,True除非None在这种情况下考虑对象,否则将考虑该对象False.

在第二个测试中,比较对象的相等性None.在这里,我们问对象,"你是否等于这个其他价值?"这是使用以下算法完成的:

    如果对象有一个__eq__方法,则调用它,然后将返回值转换为abool值并用于确定结果if.

    否则,如果对象有__cmp__方法,则调用它.此函数必须返回int指示两个对象的顺序(-1if self < other,0if self == other,+1if 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


虽然技术上是正确的,但这并不能解释元组,列表,dicts,strs,unicodes,int,floats等都有__nonzero__.依赖于内置类型的真值比依赖自定义__nonzero__方法更常见.

2> S.Lott..:

这些实际上都是不良做法.曾几何时,认为随意对待None和False是可以的.但是,从Python 2.2开始,这不是最好的策略.

首先,当你进行一种if xif not x那种测试时,Python必须隐式转换x为boolean.bool函数的规则描述了一大堆错误的东西; 其他一切都是真的.如果x的值在开始时没有正确的布尔值,那么这种隐式转换实际上并不是最清楚的说法.

在Python 2.2之前,没有bool函数,所以它更不清楚.

其次,你不应该真的测试== None.你应该使用is Noneis not None.

请参阅PEP 8,Python代码样式指南.

- 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!

有多少单身人士?五:None,True,False,NotImplementedEllipsis.因为你真的不太可能使用NotImplemented或者Ellipsis,你永远不会说if x is True(因为只是if x更清楚),你只会测试None.


第二种形式绝对不是不好的做法.PEP 8建议使用if x _twice_.首先是序列(而不是使用len),然后是True和False(而不是使用is).实际上我见过的所有Python代码都使用x,如果不是x.

3> badp..:

因为None并不是唯一被认为是错误的东西.

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."

False,0,(),[],{}""是从各个不同的None,所以你的两段代码是等价的.

此外,请考虑以下事项:

>>> False == 0
True
>>> False == ()
False

if object:不是相等性检查.0,(),[],None,{},等所有彼此不同,但他们都评价为False.

这是短路表达背后的"魔力",如:

foo = bar and spam or eggs

这是简写​​:

if bar:
    foo = spam
else:
    foo = eggs

虽然你真的应该写:

foo = spam if bar else egg

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有