例如,如果通过以下步骤:

a = []

如何检查a是否为空?


当前回答

print('not empty' if a else 'empty')

更实用一点:

a.pop() if a else None

最短版本:

if a: a.pop() 

其他回答

在真值测试中,空列表本身被认为是错误的(请参见python文档):

a = []
if a:
     print("not empty")

达伦·托马斯的回答:

编辑:反对测试的另一点空列表为False:多态性?你不应该依赖列表是列表。它应该只是像鸭子一样呱呱叫-你怎么样让你的duckCollection呱呱叫当它没有元素时为“False”?

duckCollection应该实现__nonzero_或__len__,因此if-a:将毫无问题地工作。

print('not empty' if a else 'empty')

更实用一点:

a.pop() if a else None

最短版本:

if a: a.pop() 

受到dubiusjim解决方案的启发,我建议使用一个额外的常规检查,看看它是否可以迭代:

import collections
def is_empty(a):
    return not a and isinstance(a, collections.Iterable)

注意:如果希望排除空字符串,则字符串被认为是可迭代的add,而不是isinstance(a,(str,unicode))

测试:

>>> is_empty('sss')
False
>>> is_empty(555)
False
>>> is_empty(0)
False
>>> is_empty('')
True
>>> is_empty([3])
False
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty(())
True

检查列表是否为空的最佳方法例如,如果通过以下步骤:a=[]如何检查a是否为空?

简短回答:

将列表放在布尔上下文中(例如,使用if或while语句)。如果为空,则测试False,否则测试True。例如:

if not a:                           # do this!
    print('a is an empty list')

第8段

PEP8是Python标准库中Python代码的官方Python风格指南,它断言:

对于序列(字符串、列表、元组),请使用空序列为false的事实。是:如果不是seq:如果seq:否:如果len(seq):如果不是len(seq):

我们应该期望标准库代码应该尽可能高性能和正确。但为什么会这样,为什么我们需要这种指导?

解释

我经常从刚接触Python的经验丰富的程序员那里看到这样的代码:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

懒惰语言的用户可能会这样做:

if a == []:                         # Don't do this!
    print('a is an empty list')

这些在各自的其他语言中都是正确的。这在Python中甚至是语义正确的。

但我们认为它是非Python的,因为Python通过布尔强制在列表对象的接口中直接支持这些语义。

从文档中(并特别注意空列表的包含,[]):

默认情况下,除非对象的类定义返回False的__bool__()方法或__len__()方法当使用对象调用时,返回零。以下是大多数被认为是假的内置对象:常量定义为false:None和false。任何数字类型的零:0,0.0,0j,十进制(0),分数(0,1)空序列和集合:“”,(),[],{},set(),range(0)

以及数据模型文档:

对象__布尔_(自身)调用以实现真值测试和内置操作bool();应返回False或True。当未定义该方法时,__如果定义了len__(),则调用它,如果结果为非零,则该对象视为真。如果类既没有定义__len__()也不是__bool_(),它的所有实例都被认为是真的。

and

对象__len__(自己)调用以实现内置函数len()。应该返回对象的长度,一个大于等于0的整数。此外,未定义__bool__()方法且__len__()方法返回零的对象在布尔上下文中被视为false。

因此,与此相反:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

或者:

if a == []:                     # Don't do this!
    print('a is an empty list')

执行以下操作:

if not a:
    print('a is an empty list')

做Pythonic通常会在表演中获得回报:

它有回报吗?(请注意,执行等效操作的时间越短越好:)

>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435

对于scale,这里是调用函数、构造和返回空列表的成本,您可以从上面使用的空检查的成本中减去该成本:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

我们看到,使用内置函数len(与0相比)检查长度,或者检查空列表,都比使用所记录的语言的内置语法性能差得多。

Why?

对于len(a)==0,检查:

首先,Python必须检查全局变量,以查看len是否被隐藏。

然后,它必须调用函数,加载0,并在Python中进行相等比较(而不是使用C):

>>> import dis
>>> dis.dis(lambda: len([]) == 0)
  1           0 LOAD_GLOBAL              0 (len)
              2 BUILD_LIST               0
              4 CALL_FUNCTION            1
              6 LOAD_CONST               1 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

对于[]==[],它必须构建一个不必要的列表,然后再次在Python的虚拟机中执行比较操作(与C相反)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

“Pythonic”方法是一种更简单、更快的检查方法,因为列表的长度缓存在对象实例头中:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

C来源的证据和文件

PyVarObject这是PyObject的扩展,添加了ob_size字段。这仅用于具有某种长度概念的对象。这种类型不经常出现在Python/C API中。它对应于由PyObject_VAR_HEAD宏展开定义的字段。

从Include/listobject.h中的c源代码:

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

对评论的回应:

我要指出的是,这对于非空情况也是如此,尽管它很难看,如l=[],然后%timeitlen(l)!=0 90.6纳秒±8.3纳秒,%时间l!=[]55.6 ns±3.09,%时间不超过38.5 ns±0.372。但是,尽管速度是原来的三倍,但没有人会喜欢我。这看起来很可笑。但速度取胜我想问题是用timeit测试,因为仅当l:足够,但令人惊讶的是%timeit bool(l)产生101 ns±2.64 ns。有趣的是,如果没有这种惩罚,就没有办法强迫发出嘘声。%时间是无用的,因为不会发生转换。

IPython魔法%timeit在这里并非完全无用:

In [1]: l = []                                                                  

In [2]: %timeit l                                                               
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

In [3]: %timeit not l                                                           
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [4]: %timeit not not l                                                       
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

我们可以看到,每增加一项都会有一点线性成本。我们希望看到成本相同,也就是说,所有其他方面都是平等的——所有其他方面尽可能最小化:

In [5]: %timeit if l: pass                                                      
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [6]: %timeit if not l: pass                                                  
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [7]: %timeit if not not l: pass                                              
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

现在,让我们来看一个非空列表的例子:

In [8]: l = [1]                                                                 

In [9]: %timeit if l: pass                                                      
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [10]: %timeit if not l: pass                                                 
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [11]: %timeit if not not l: pass                                             
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

我们在这里看到的是,无论是将实际布尔值传递给条件检查还是传递给列表本身,都没有什么不同,如果有什么不同的话,那么给出列表的速度会更快。

Python是用C编写的;它使用C级的逻辑。用Python编写的任何内容都会比较慢。除非您直接使用Python内置的机制,否则它可能会慢几个数量级。

您甚至可以尝试像这样使用bool()。虽然它的可读性较低,但它确实是一种简洁的方法。

    a = [1,2,3];
    print bool(a); # it will return True
    a = [];
    print bool(a); # it will return False

我喜欢这种方式,因为检查列表是否为空。

非常方便和有用。