如果A vs如果A不是None:

时间:2011-10-19 03:55:06

标签: python

我可以使用:

if A:

而不是

if A is not None:

后者似乎很冗长。有区别吗?

13 个答案:

答案 0 :(得分:125)

声明

if A:

将调用A.__nonzero__()(请参阅Special method names文档)并使用该函数的返回值。以下是摘要:

  

object.__nonzero__(self)

     

被要求实施真值测试和内置操作bool();应该返回FalseTrue,或等值整数01。如果未定义此方法,则调用__len__()(如果已定义),如果对象的结果非零,则认为该对象为true。如果某个类既未定义__len__()也未定义__nonzero__(),则其所有实例都被视为true。

另一方面,

if A is not None:

引用ANone进行比较,看它是否相同。

答案 1 :(得分:47)

正如PEP8所述:

  
      
  • 应该始终与 等单身人士进行比较   '是'或'不是',绝不是平等运算符

         

    另外,当你真正的意思是“如果x不是无”时,要小心写“if x”    - 例如在测试默认的变量或参数时   没有设置为其他值。另一个值可能有一个类型   (例如容器)在布尔上下文中可能为false!

  •   

答案 2 :(得分:16)

如果没有合适的结果,很多函数都会返回None。例如,如果结果中没有行,则SQLAlchemy查询的.first()方法将返回None。假设您选择的值可能返回0并且需要知道它是否实际为0或者查询是否完全没有结果。

一个常见的习惯用法是给函数或方法的可选参数设置默认值None,然后测试该值为None以查看是否指定了它。例如:

def spam(eggs=None):
    if eggs is None:
        eggs = retrievefromconfigfile()

将其与:

进行比较
def spam(eggs=None):
    if not eggs:
        eggs = retrievefromconfigfile()

在后者中,如果您致电spam(0)spam([])会怎样?该函数将(错误地)检测到您没有传入eggs的值并为您计算默认值。这可能不是你想要的。

或者设想像“返回给定帐户的交易清单”之类的方法。如果该帐户不存在,则可能返回None。这与返回空列表不同(这意味着“此帐户存在但未记录事务)。

最后,回到数据库的东西。 NULL和空字符串之间有很大的区别。一个空字符串通常表示“这里有一个值,而这个值根本就没有”。 NULL表示“尚未输入此值。”

在每种情况下,您都希望使用if A is None。您正在检查特定值 - 无 - 不仅仅是“任何碰到False的值”。

答案 3 :(得分:16)

if x: #x is treated True except for all empty data types [],{},(),'',0 False, and None

所以它与

不一样
if x is not None # which works only on None

答案 4 :(得分:9)

他们做的事情非常不同

以下检查A是否包含值False[]None''0以外的任何内容。它会检查A的

if A:

以下检查A是否是与None不同的对象。它检查并比较A和无的参考(内存地址)。

if A is not None:

更新:进一步说明

很多时候这两个人似乎做同样的事情,所以很多人互换地使用它们 - 这是一个非常糟糕的主意。由于优化了解释器/编译器,如interning或其他原因,两者给出相同结果的原因是纯重合很多次。

考虑到这些优化,相同值的整数和字符串最终会使用相同的内存空间。这可能解释了为什么两个单独的字符串就好像它们是相同的。

> a = 'test'
> b = 'test'
> a is b
True
> a == b
True

其他事情虽然表现不一样。

> a = []
> b = []
> a is b
False
> a == b
True

这两个清单显然有自己的记忆。令人惊讶的是,元组表现得像字符串一样。

> a = ()
> b = ()
> a is b
True
> a == b
True

可能这是因为元组保证不会改变,因此重用相同的内存是有意义的。

这样做的底线是你不能依赖巧合。仅仅因为它像鸭子一样嘎嘎叫它并不意味着它是一只鸭子。根据您真正想要检查的内容,使用is==。这些事情可能很难调试,因为is读起来像散文,我们经常只是略过它。

答案 5 :(得分:7)

如果A:如果A为0,False或None,则证明为假,这可能导致不良结果。

答案 6 :(得分:6)

我见过的大多数指南建议您使用

如果A:

除非你有理由更具体。

有一些细微的差别。除了None之外还有返回False的值,例如空列表,或者0,因此请考虑一下您正在测试的内容。

答案 7 :(得分:5)

无是Python中的特殊值,通常指定未初始化的变量。要测试A是否没有此特定值,请使用:

if A is not None

虚假值是Python中特殊的对象类(例如false,[])。要测试A是否为假,请使用:

if not A

因此,两个表达式不一样而且最好不要将它们视为同义词。

P.S。没有也是假的,所以第一个表达意味着第二个。但第二个除了无之外还包括其他虚假值。现在......如果你可以确定除A中的None之外你不能有其他的假值,那么你可以用第二个表达式替换第一个表达式。

答案 8 :(得分:4)

这取决于具体情况。

当我期望if A:成为某种集合时,我使用A,如果集合不为空,我只想执行该块。这允许调用者传递任何表现良好的集合,无论是否为空,并让它按照我的预期进行。它还允许NoneFalse禁止执行块,这有时会方便调用代码。

OTOH,如果我希望A成为一些完全随意的对象,但它可能默认为None,那么我总是使用if A is not None,调用代码可能故意传递对空集合,空字符串或0值数字类型或布尔False的引用,或者在布尔上下文中恰好为false的某个类实例。

另一方面,如果我希望A是一些更具体的东西(例如我要调用方法的类的实例),但它可能默认为{{ 1}},我认为默认的布尔转换是我不介意对所有子类强制执行的类的属性,然后我将使用None来保存我的手指输入额外12的可怕负担字符。

答案 9 :(得分:3)

前者更像Pythonic(更好的意识形态代码),但如果A为False(不是None),则不会执行该块。

答案 10 :(得分:3)

其他答案都提供了很好的信息,但我觉得这需要说清楚。

不,你永远不应该使用:

if A:

如果您需要测试的是:

if A is not None:

第一个通常可以替代第二个,但第一个是难以找到错误的常见来源。即使您所做的只是编写一些快速丢弃的代码,也不应该让自己养成编写错误代码的习惯。训练您的手指和思维来书写和阅读正确的冗长形式的测试:

if A is not None: 

None 的常见用途是定义可选参数值,并给变量一个默认的起始值,表示“还没有值”,函数表示“没有返回值”。如果你写一个函数如:

def my_func(a_list, obj=None):
    if obj:          # Trying to test if obj was passed
        a_list.append(obj)
    # do something with a_list

这适用于许多现实世界的用途,例如:

my_func(user_names, "bob")

但如果发生这种情况:

my_func(user_names, "")
my_func(user_names, [])
my_func(user_names, 0)

那么零长度对象将不会被添加到列表中。编写第一个代码时,您可能知道不允许使用零长度的用户名。所以短代码工作正常。但是随后您尝试修改代码以使用空字符串来表示无名匿名用户之类的东西,突然此函数停止执行预期执行的操作(将匿名用户添加到列表中)。

例如,假设您有逻辑来定义何时允许用户登录,如下所示:

new_user = get_user_name()

if user_list_ok(my_func(current_users, new_user)):
    # user_list_ok() tests that no more than 10 users can
    # log in at the same time, and that no sigle user can
    # can log in more than 3 times at once.

    # This user is allowed to log in!

    log_user_in(new_user)

这现在会在您的代码中产生微妙而复杂的错误。 “”的匿名用户不会被添加到测试列表中,所以当系统达到10个用户的限制时,测试仍然会允许匿名用户登录,将用户数推到11。这样可能会触发系统其他部分的错误,即最多只需要 10 个用户。

当您需要测试“var 没有值”时,您应该始终使用更长的“is not None”测试,即使它看起来很丑陋和冗长。

答案 11 :(得分:2)

我创建了一个名为test.py的文件,并在解释器上运行它。你可以改变自己想要的东西,测试幕后的情况。

import dis

def func1():

    matchesIterator = None

    if matchesIterator:

        print( "On if." );

def func2():

    matchesIterator = None

    if matchesIterator is not None:

        print( "On if." );

print( "\nFunction 1" );
dis.dis(func1)

print( "\nFunction 2" );
dis.dis(func2)

这是汇编程序的区别:

来源:

>>> import importlib
>>> reload( test )

Function 1
  6           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

  8           6 LOAD_FAST                0 (matchesIterator)
              9 POP_JUMP_IF_FALSE       20

 10          12 LOAD_CONST               1 ('On if.')
             15 PRINT_ITEM
             16 PRINT_NEWLINE
             17 JUMP_FORWARD             0 (to 20)
        >>   20 LOAD_CONST               0 (None)
             23 RETURN_VALUE

Function 2
 14           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

 16           6 LOAD_FAST                0 (matchesIterator)
              9 LOAD_CONST               0 (None)
             12 COMPARE_OP               9 (is not)
             15 POP_JUMP_IF_FALSE       26

 18          18 LOAD_CONST               1 ('On if.')
             21 PRINT_ITEM
             22 PRINT_NEWLINE
             23 JUMP_FORWARD             0 (to 26)
        >>   26 LOAD_CONST               0 (None)
             29 RETURN_VALUE
<module 'test' from 'test.py'>

答案 12 :(得分:1)

python&gt; = 2.6,

如果我们写

if A:

将生成警告,

  

FutureWarning:此方法的行为将来会发生变化   版本。使用特定的'len(elem)'或'elem is not None'测试   代替。

所以我们可以使用

if A is not None:
相关问题