如果A和A不是无:
我可以用吗:
if A:
代替
if A is not None:
后者似乎非常冗长。 有区别吗?
该声明
if A:
将调用A.__nonzero__()
(请参阅特殊方法名称文档)并使用该函数的返回值。 这里是总结:
object.__nonzero__(self)
被调用来实现真值testing和内置操作
bool()
; 应该返回False
或True
,或者它们的整数等于0
或1
。 当这个方法没有被定义的时候,__len__()
被调用,如果它被定义的话,那么如果这个对象的结果是非零的,它就被认为是真的。 如果一个类既没有定义__len__()
也没有定义__nonzero__()
,所有的实例都被认为是真的。
另一方面,
if A is not None:
只比较参考A
和None
,看看是否相同。
正如PEP8所写 :
像None这样的单身人士的比较应该总是用'is'或'is not'来完成,而不是平等运算符 。
另外, 当你真正的意思是“如果x不是无”时 , 要小心写“if x” – 例如,当testing一个variables或默认为None的参数是否被设置为其他值。 另一个值可能有一个types(如一个容器),在布尔上下文中可能是false!
如果没有合适的结果,许多函数将返回None。 例如,如果结果中没有行,SQLAlchemy查询的.first()
方法将返回None。 假设你select了一个可能返回0的值,并且需要知道它是否实际为0或者查询是否完全没有结果。
一个常见的习惯用法是给函数或方法的可选参数默认值None,然后testing该值为None来查看它是否被指定。 例如:
def spam(eggs=None): if eggs is None: eggs = retrievefromconfigfile()
比较:
def spam(eggs=None): if not eggs: eggs = retrievefromconfigfile()
在后者中,如果您调用spam(0)
或spam([])
会发生什么情况? 该函数会(错误地)检测到你没有传入一个eggs
的值,并会为你计算一个默认值。 这可能不是你想要的。
或者想像一种像“返回给定账户的交易清单”的方法。 如果该帐户不存在,则可能会返回无。 这不同于返回一个空的列表(这意味着“这个帐户存在,但没有logging交易)。
最后回到数据库的东西。 NULL和空string之间有很大的区别。 一个空string通常会说“这里有价值,而这个价值根本就没有”。 NULL表示“这个值没有被input”。
在每一种情况下, if A is None
,你就可以使用。 你正在检查一个特定的值 – 没有 – 不只是“发生任何虚假的值”。
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
如果A:如果A为0,False或None,则certificate是错误的,这会导致不希望的结果。
我见过的大多数指南都build议你应该使用
如果一个:
除非你有一个更具体的理由。
有一些细微的差别。 除了None以外的其他值都返回False,例如空列表或0,所以请考虑一下你真正testing的是什么。
这取决于上下文。
我使用, if A:
当我期待A
是某种集合,我只想执行该块如果收集不是空的。 这允许调用者传递任何行为良好的集合,不pipe是否为空,并使其按照我所期望的那样进行。 它也允许None
和False
来禁止块的执行,这对于调用代码是偶然的。
OTOH,如果我期望A
是一个完全随意的对象,但它可能默认为None
,那么我总是使用if A is not None
,因为调用代码可能故意传递一个空集合的引用,空string或0值的数字types,或者布尔型的False
,或者在布尔上下文中碰巧为假的某个类实例。
另一方面,如果我期望A
是一些更具体的东西(例如一个类的实例,我将调用方法),但它可能已被默认为None
,我认为默认布尔转换为是我不介意在所有子类上执行的类的一个属性,那么我将使用if A:
保存我的手指input额外的12个字符的可怕负担。
在Python中 , 没有一个是通常指定一个未初始化variables的特殊值 。 要testingA是否没有这个特定的值,你可以使用:
if A is not None
Falsey值是Python中一类特殊的对象 (例如false,[])。 要testingA是否是错误的使用:
if not A
因此,这两个expression式是不一样的你最好不要把它们当成同义词。
PS无也是错误的,所以第一个expression意味着第二个expression。 但是第二个涵盖了除了None之外的其他伪造的值。 现在…如果你可以确定你在A中除了None之外还没有其他的错误值,那么你可以用第二个expression式replace第一个expression式。
他们做了非常不同的事情 。
下面检查A是否有除False
, []
, None
, ''
和0
之外的任何值。 它检查A的值
if A:
下面检查A是否与None不同。 它检查并比较A和None的引用 (内存地址)。
if A is not None:
更新:进一步的解释
很多时候,两个人似乎做同样的事情,所以很多人交替使用它们 – 这是一个非常糟糕的主意。 由于解释器/编译器的优化如同实习或其他的原因,这两者给出相同结果的原因多次是纯巧合 。
考虑到这些优化,具有相同值的整数和string最终使用相同的存储空间。 这可能解释了为什么两个单独的string就像是相同的。
> a = 'test' > b = 'test' > a is b True > a == b True
其他的事情不尽相同
> a = [] > b = [] > a is b False > a == b True
这两个清单显然有自己的记忆。 令人惊讶的是,元组的行为像string。
> a = () > b = () > a is b True > a == b True
可能这是因为元组保证不会改变,所以重用相同的内存是有意义的。
底线是,你不能依靠巧合 。 只因为它像鸭子一样呱呱叫,并不意味着它是一只鸭子。 使用is
和==
取决于你真正想检查的东西。 这些东西可能很难debugging,因为阅读就像散文,我们经常只是略过。
前者更Pythonic(更好的意识代码),但不会执行该块如果A是假的(而不是无)。
python> = 2.6,
如果我们写如
if A:
会产生警告,
FutureWarning:这个方法的行为在未来的版本中将会改变。 而是使用特定的“len(elem)”或“elem is not None”testing。
所以我们可以使用
if A is not None:
我创build了一个名为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'>