如果A vs如果A不为None:

问题:如果A vs如果A不为None:

我可以用吗:

if A:

代替

if A is not None:

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

Can I use:

if A:

instead of

if A is not None:

The latter seems so verbose. Is there a difference?


回答 0

该声明

if A:

将调用A.__nonzero__()(请参阅特殊方法名称文档)并使用该函数的返回值。总结如下:

object.__nonzero__(self)

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

另一方面,

if A is not None:

将参考A与进行比较None以查看其是否相同。

The statement

if A:

will call A.__nonzero__() (see Special method names documentation) and use the return value of that function. Here’s the summary:

object.__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, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __nonzero__(), all its instances are considered true.

On the other hand,

if A is not None:

compares only the reference A with None to see whether it is the same or not.


回答 1

PEP8所述

  • 与单例(如None)的 比较应始终使用“ is”或“ is not”进行,永远不要使用相等运算符进行

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

As written in PEP8:

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


回答 2

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
if x: #x is treated True except for all empty data types [],{},(),'',0 False, and None

so it is not same as

if x is not None # which works only on None

回答 3

如果没有适当的结果,很多函数将返回None。例如,.first()如果结果中没有行,则SQLAlchemy查询的方法将返回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并会为您计算默认值。那可能不是您想要的。

或设想一种诸如“返回给定帐户的交易列表”之类的方法。如果该帐户不存在,则可能返回无。这不同于返回一个空列表(这意味着“此帐户存在,但尚未记录交易”)。

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

在每种情况下,您都想使用if A is None。您正在检查一个特定的值-无-不只是“碰巧转换为False的任何值”。

A lot of functions return None if there are no appropriate results. For example, an SQLAlchemy query’s .first() method returns None if there were no rows in the result. Suppose you were selecting a value that might return 0 and need to know whether it’s actually 0 or whether the query had no results at all.

A common idiom is to give a function or method’s optional argument the default value of None, and then to test that value being None to see if it was specified. For example:

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

compare that to:

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

In the latter, what happens if you call spam(0) or spam([])? The function would (incorrectly) detect that you hadn’t passed in a value for eggs and would compute a default value for you. That’s probably not what you want.

Or imagine a method like “return the list of transactions for a given account”. If the account does not exist, it might return None. This is different than returning an empty list (which would mean “this account exists but has not recorded transactions).

Finally, back to database stuff. There’s a big difference between NULL and an empty string. An empty string typically says “there’s a value here, and that value is nothing at all”. NULL says “this value hasn’t been entered.”

In each of those cases, you’d want to use if A is None. You’re checking for a specific value – None – not just “any value that happens to cast to False”.


回答 4

他们做的事情截然不同

下面的检查是否有不同的价值观什么False[]None''0。它检查A 的

if A:

下面检查A是否是不同于None的对象。它检查并比较A和None 的引用(内存地址)。

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我们常常只是略读散文,就像散文一样。

They do very different things.

The below checks if A has anything except the values False, [], None, '' and 0. It checks the value of A.

if A:

The below checks if A is a different object than None. It checks and compares the reference (memory address) of A and None.

if A is not None:

UPDATE: Further explanation

Many times the two seem to do the same thing so a lot of people use them interchangeably. The reason the two give the same results is many times by pure coincidence due to optimizations of the interpreter/compiler like interning or something else.

With those optimizations in mind, integers and strings of the same value end up using the same memory space. That probably explains why two separate strings act as if they are the same.

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

Other things don’t behave the same though..

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

The two lists clearly have their own memory. Surprisingly tuples behave like strings.

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

Probably this is because tuples are guaranteed to not change, thus it makes sense to reuse the same memory.

This shows that you should be extra vigilant on what comparison operator you use. Use is and == depending on what you really want to check. These things can be hard to debug since is reads like prose that we often just skim over it.


回答 5

if A: 如果A为0,False,空字符串,空列表或None,则将证明为false,这可能导致不良结果。

if A: will prove false if A is 0, False, empty string, empty list or None, which can lead to undesired results.


回答 6

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

如果一个:

除非您有理由更具体。

有一些细微的差异。除了None以外,还有其他值返回False,例如空列表或0,因此请考虑一下您真正要测试的内容。

Most guides I’ve seen suggest that you should use

if A:

unless you have a reason to be more specific.

There are some slight differences. There are values other than None that return False, for example empty lists, or 0, so have a think about what it is you’re really testing for.


回答 7

在Python中none是一个特殊值,通常会指定一个未初始化的变量。要测试A是否不具有此特定值,请使用:

if A is not None

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

if not A

因此,这两个表达式并不相同,您最好不要将它们视为同义词。


PS None也是假的,因此第一个表达式表示第二个表达式。但是第二个覆盖了除None之外的其他虚假值。现在…如果您可以确定除了A中的None以外,不能有其他虚假值,则可以将第二个表达式替换为第一个表达式。

None is a special value in Python which usually designates an uninitialized variable. To test whether A does not have this particular value you use:

if A is not None

Falsey values are a special class of objects in Python (e.g. false, []). To test whether A is falsey use:

if not A

Thus, the two expressions are not the same And you’d better not treat them as synonyms.


P.S. None is also falsey, so the first expression implies the second. But the second covers other falsey values besides None. Now… if you can be sure that you can’t have other falsey values besides None in A, then you can replace the first expression with the second.


回答 8

这取决于上下文。

if A:在希望A成为某种集合时使用,并且我只想在集合不为空的情况下执行该块。这使调用者可以传递任何行为良好的集合(无论是否为空),并使其按照我的期望进行。它还允许NoneFalse禁止执行该块,这有时会方便调用代码。

OTOH,如果我希望A是一个完全任意的对象,但可能默认将其设置为None,则我始终使用if A is not None,因为调用代码可能故意将对空集合,空字符串或0值数字类型的引用传递给它,或者布尔值False或在布尔上下文中碰巧为false的某个类实例。

另一方面,如果我期望A是更特定的东西(例如,我要调用其方法的类的实例),但它可能已默认为None,并且我认为默认布尔转换为我不介意在所有子类上强制执行该类的属性,那么我将使用它if A:来省掉输入额外12个字符的沉重负担,从而省去了手指的麻烦。

It depends on the context.

I use if A: when I’m expecting A to be some sort of collection, and I only want to execute the block if the collection isn’t empty. This allows the caller to pass any well-behaved collection, empty or not, and have it do what I expect. It also allows None and False to suppress execution of the block, which is occasionally convenient to calling code.

OTOH, if I expect A to be some completely arbitrary object but it could have been defaulted to None, then I always use if A is not None, as calling code could have deliberately passed a reference to an empty collection, empty string, or a 0-valued numeric type, or boolean False, or some class instance that happens to be false in boolean context.

And on the other other hand, if I expect A to be some more-specific thing (e.g. instance of a class I’m going to call methods of), but it could have been defaulted to None, and I consider default boolean conversion to be a property of the class I don’t mind enforcing on all subclasses, then I’ll just use if A: to save my fingers the terrible burden of typing an extra 12 characters.


回答 9

我创建了一个名为的文件,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'>

I created a file called test.py and ran it on the interpreter. You may change what you want to, to test for sure how things is going on behind the scenes.

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)

This is the assembler difference:

Source:

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

回答 10

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

The former is more Pythonic (better ideomatic code), but will not execute the block if A is False (not None).


回答 11

python> = 2.6,

如果我们写这样

if A:

将产生警告,

FutureWarning:此方法的行为将在将来的版本中更改。而是使用特定的“ len(elem)”或“ elem不是None”测试。

所以我们可以使用

if A is not None:

python >= 2.6,

if we write such as

if A:

will generate warning as,

FutureWarning: The behavior of this method will change in future versions. Use specific ‘len(elem)’ or ‘elem is not None’ test instead.

So we can use

if A is not None: