Python中的"if len(A) is not 0"和"if A"语句的区别

16

我的同事在这种情况下使用这种方式

if len(A) is not 0:
    print('A is not empty')

我更喜欢这个

if A:
    print('A is not empty')

什么是正反两方论证?

她的观点是第一种方式更直接地表达了她确切的意图。我的观点是我的方式更加简洁。

同时,第一种方式比我的方式快两倍:

>>> import timeit
>>> timeit.timeit('len(A) is not 0', setup='A=[1,2,3]')
0.048459101999924314
>>> timeit.timeit('bool(A)', setup='A=[1,2,3]')
0.09833707799998592

但是

>>> import timeit
>>> timeit.timeit('if len(A) is not 0:\n  pass', setup='A=[1,2,3]')
0.06600062699999398
>>> timeit.timeit('if A:\n  pass', setup='A=[1,2,3]')
0.011816206999810674 

第二种方式快了6倍!我不明白if语句是如何工作的 :-)


10
if len(A) is not 0: 这种写法存在风险,因为这并不能保证引用的是同一对象(使用 isis not 会进行引用检查)。而 if A 可以测试真实性(空值),比较安全。 - cs95
2
在任何情况下都不应该使用“is not 0”。应该使用“!=0”。 - khelwood
3
@vladimirfol:这是具体实现相关的。你能给我展示一下Python文档中哪里说它们保证是相同的吗? - cdarke
2
@vladimirfol x = 257; x is 257 失败。CPython 只会对小整数进行内部化处理。 - L3viathan
2
@L3viathan:在 Idle (3.6.6) 中,这是 True。如果我将语句写在不同的行中,则会失败。 - Matthias
显示剩余4条评论
4个回答

21

PEP 8风格指南明确了这一点:

对于序列(字符串、列表、元组),使用空序列为假的事实。

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

2
但是要小心处理Numpy数组:虽然bool([0])bool([False])的结果为True,但是bool(numpy.array([0]))bool(numpy.array([False]))的结果为False,因此在这种特殊情况下应该明确使用len - Géry Ogam
1
我同时赞同和不赞同,PEP是一种惯例,我们应该意识到它的存在,但并非一条规则。现在有另一种观点,我喜欢遵循:https://dev59.com/TL3pa4cB1Zd3GeqPd23k#64070199 - mseromenho

3
我认为,如果A = 42,你同事的代码会抛出错误。
object of type 'int' has no len()

如果您的代码只会执行if语句后面的内容,那么您可以使用while语句。


2
如果代码期望一个列表,那么这似乎不是什么问题。 - deceze
没错,但如果你总是使用它,我可以保证,在某个时刻,你可能会得到一个不同于列表的输入,这样你就需要花费大量时间来调试。 - Statistic Dean
2
相反,这会因为意外的类型而引发一个可见的异常,而不是默默地忽略问题。 - deceze
@StatisticDean 我不确定你是在说这是好事还是坏事 - 在我看来,通常情况下,当输入不符合预期时,您希望代码出错 - 这是支持“同事代码”的一个观点(尽管其他答案已经说过,OP的代码是正确的Python实现)。 - Stael
@Stael 我并不持任何立场,只是指出其中的区别。总的来说,我同意你的观点,宁愿出现错误也不希望代码以错误的方式执行。 - Statistic Dean

2

1.

if len(A) is not 0:
    print('A is not empty')

2.

if A:
    print('A is not empty')

第一种和第二种方法的区别在于,您只能对列表、元组、字典等支持len()函数的数据结构使用len(A),而不能对字符、字符串、整数等非数据结构类型使用len()函数。请注意,保留html标签。
例如: len(123)、len(abc)和len(123abc)会引发错误。
但是, list = [1,2,3,4,5] len(list)不会引发错误。
if A:
    statement  # this is useful while our only concern is that the variable A has some value or not 

1
您没有在比较同一件事情。如果您比较这个:
import timeit
print(timeit.timeit('if len(A) is not 0:\n  pass', setup='A=[1,2,3]'))
print(timeit.timeit('if A:\n  pass', setup='A=[1,2,3]'))

你会发现你的方法更快。 此外,你的方法是一种更具Python风格的方式。


哈哈,为什么它更快?我以为如果进行布尔评估就会变慢。 - vladimirfol
0.066秒对比0.0118秒!快了6倍!我现在对if语句的工作原理感到困惑 :-) - vladimirfol
1
它更快,因为它使用一个内置函数来计算“len(A)>0”,而不是多个函数。至少我认为是这样,如果您感兴趣,我可以再深入挖掘一下确保正确性。 - T.Lucas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接