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

时间:2008-09-19 09:29:19

标签: python

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

if not someobj:
    #do something

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

if someobj == None:
    #do something

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

9 个答案:

答案 0 :(得分:172)

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

  1. 如果对象具有__nonzero__特殊方法(与数字内置函数intfloat一样),则会调用此方法。它必须返回直接使用的bool值,或者如果等于零则返回int False值。

  2. 否则,如果对象具有__len__特殊方法(容器内置插件,listdictset,{{1} },...),如果容器tuple为空(长度为零),则调用此方法。

  3. 否则,该对象将被视为False,除非它是True,在这种情况下,它被视为None

  4. 在第二个测试中,将对象与False进行相等性比较。在这里,我们问对象,“你是否等于这个其他值?”这是使用以下算法完成的:

    1. 如果对象具有None方法,则会调用该方法,然后将返回值转换为__eq__值并用于确定bool的结果

    2. 否则,如果对象具有if方法,则调用它。此函数必须返回__cmp__,指示两个对象的顺序(int如果-1self < other如果0self == other if {{ 1}})。

    3. 否则,对象的身份进行比较(即,他们引用同一个对象,可以由+1运算符进行测试)。

    4. 使用self > other运算符可以进行另一项测试。 我们会问对象,“你是这个特殊的对象吗?”

      一般情况下,我建议使用非数值的第一个测试,当你想要比较相同性质的对象(两个字符串,两个数字......)并检查时,使用测试进行相等仅在使用标记值时才标识(is表示未针对例如成员字段初始化,或者使用isNone方法时)。

      总结一下,我们有:

      getattr

答案 1 :(得分:45)

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

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

在Python 2.2之前,没有bool函数,因此它更不清楚。

其次,你不应该用== None进行真正的测试。您应该使用is Noneis not None

参见PEP 8,Style Guide for Python Code

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

有多少单身人士?五:NoneTrueFalseNotImplementedEllipsis。由于您真的不太可能使用NotImplementedEllipsis,并且您永远不会说if x is True(因为简单地if x更加清晰),您只会测试None

答案 2 :(得分:32)

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

False0()[]{}""都与None不同,所以两个代码段不等于

此外,请考虑以下事项:

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

if object: 是一个等式检查。 0()[]None{} 彼此不同,但它们全部< em>评估为False。

这是短路表达式背后的“魔力”,如:

foo = bar and spam or eggs

这是:

的简写
if bar:
    foo = spam
else:
    foo = eggs

虽然你真的应该写:

foo = spam if bar else egg

答案 3 :(得分:3)

PEP 8 -- Style Guide for Python Code建议您使用 ,如果您要测试的是岬

- Comparisons to singletons like None should always be done with
  'is' or 'is not', never the equality operators.

另一方面,如果你测试的不是None-ness,你应该使用布尔运算符。

答案 4 :(得分:3)

如果你问

if not spam:
    print "Sorry. No SPAM."

垃圾邮件 __非零__ 方法被调用。从Python手册:

  

<强> __非零__ )     被称为实施真值测试,内置操作bool();应该返回False或True,或者它们的整数等价于0或1.如果未定义此方法,则调用__len __()(如果已定义)(见下文)。如果一个类既没有定义__len __()也没有定义__nonzero __(),那么它的所有实例都被认为是真的。

如果你问

if spam == None:
    print "Sorry. No SPAM here either."
使用参数调用垃圾邮件 __ eq __ 方法。

有关自定义可能性的更多信息,请查看https://docs.python.org/reference/datamodel.html#basic-customization

上的Python文档。

答案 5 :(得分:2)

这两个比较用于不同的目的。前者检查某物的布尔值,第二种检查具有无值的身份。

答案 6 :(得分:0)

首先,第一个例子更短,看起来更好。根据其他帖子,你选择的还取决于你真正想要做的比较。

答案 7 :(得分:0)

答案是“它取决于”。

如果我将0,“”,[]和False(列表并非详尽无遗)视为在此上下文中等于None,我会使用第一个示例。

答案 8 :(得分:0)

就个人而言,我选择了跨语言的一致方法:只有当var声明为boolean(或者在C中定义,我们没有特定类型)时,我才会if (var)(或等效)。我甚至用b(这实际上是bVar)为这些变量添加前缀,以确保我不会在这里意外使用其他类型。
我真的不喜欢隐式转换为布尔值,更不用说有很多复杂的规则了。

当然,人们会不同意。有些走得更远,我在工作中的Java代码中看到if (bVar == true)(对我来说太多了!),其他人喜欢太紧凑的语法,转向while (line = getNextLine())(对我来说太模糊了)。