题 如何检查列表是否为空?


例如,如果传递以下内容:

a = []

我如何检查是否 a 是空的?


2729
2017-09-10 06:20


起源




答案:


if not a:
  print("List is empty")

使用空列表的隐式布尔值是非常pythonic。


3907
2017-09-10 06:28



扮演魔鬼的拥护者。我不明白为什么这个成语被认为是pythonic。 '明确比隐含更好',对吗?关于什么是检查,这个检查似乎不是很明确。 - James McMahon
@JamesMcMahon - 它是显性和类型灵活性之间的权衡。一般来说,“明确”意味着不做“神奇”的事情。另一方面,“duck typing”意味着使用更通用的接口,而不是显式检查类型。所以像 if a == [] 是强迫特定类型(() == [] 是 False)。在这里,普遍的共识似乎是鸭子打字胜出(实际上,这样说 __nonzero__ 是测试空虚的界面 docs.python.org/reference/datamodel.html#object.__nonzero__) - andrew cooke
这在“编程建议”部分中得到了体现 PEP 8:“对于序列,(字符串,列表,元组),请使用空序列为假的事实。” - abarnert
ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()只要数组中包含某些内容,我就会看到此错误 - PirateApp
@PireattApp,你必须使用Numpy。他们谈论的是常规阵列。对于numpy,也许你想使用'is not None'? - Sam Bobel


pythonic的方法来自于 PEP 8风格指南 (哪里  意思是“推荐”和 没有 意思是“不推荐”):

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

是: if not seq:
     if seq:

没有:  if len(seq):
     if not len(seq):

865
2017-09-10 10:33



如果您希望发出信号,第二种方式似乎更好 seq 预计会成为某种类似列表的对象。 - BallpointBen
Python主张所说的@BallpointBen应尽可能隐含在变量的命名方式中 - Aalok


我明确地喜欢它:

if len(li) == 0:
    print('the list is empty')

这样就可以100%清楚了 li 是一个序列(列表),我们想测试它的大小。我的问题 if not li: ... 是它给人的错觉 li 是一个布尔变量。


519
2017-09-05 00:30



检查列表的长度是否等于零,而不仅仅是检查列表是否为假,是丑陋和单一的。任何熟悉Python的人都不会想到 li 根本就是一个布尔,并不关心。如果它很重要,您应该添加注释,而不是更多代码。 - Carl Smith
这似乎是一个不必要的精确测试,通常较慢,并且总是不太可读恕我直言。而不是检查空的大小,为什么不检查它是否为空? - John B
无论如何,这是坏的原因(并且在一般语言中使用像Python这样的强大成语的语言中违反成语)是因为它向读者发出信号,表明你是出于某种原因专门检查长度的(例如,因为你想要 None 要么 0 提出异常而不是通过)。所以,当你无缘无故地这样做时,这会产生误导 - 这也意味着你的代码 不 需要进行区分,这种区别是看不见的,因为你已经在其他所有来源中“狼来了”。 - abarnert
我认为这只是不必要地延长了代码。否则,为什么不更加“明确” if bool(len(li) == 0) is True:? - augurar
@Jabba会的 O(1) 在许多情况下(使用内置数据类型的那些),但你不能依赖它。您可能正在使用没有此属性的自定义数据类型。在编写此代码之后,您可能还决定稍后添加此自定义数据类型。 - ralokt


其他人似乎将这个问题概括为仅仅是列表,所以我想我会为很多人可能会使用的不同类型的序列添加一个警告,特别是因为这是“python test empty array”的第一个google点击。

其他方法不适用于numpy数组

你需要小心numpy数组,因为其他方法可以正常工作 lists或其他标准容器因numpy数组而失败。我在下面解释原因,但简而言之, 首选方法 是用 size

“pythonic”方式不起作用:第1部分

“pythonic”方式因numpy数组失败,因为numpy尝试将数组转换为数组 bools,和 if x 试图评估所有这些 bool对于某种总体真值,立即s。但这没有任何意义,所以你得到一个 ValueError

>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

“pythonic”方式不起作用:第2部分

但至少上面的情况告诉你它失败了。如果你碰巧有一个只有一个元素的numpy数组,那么 if 语句将“工作”,从某种意义上说,你没有得到错误。但是,如果那个元素恰好是 0 (要么 0.0, 要么 false,...),. if 语句将错误地导致 false

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

但显然 x 存在并且不是空的!这个结果不是你想要的。

运用 len 会给出意想不到的结果

例如,

len( numpy.zeros((1,0)) )

返回1,即使数组元素为零。

numpythonic方式

如中所述 scipy FAQ,在你知道你有一个numpy数组的所有情况下的正确方法是使用 if x.size

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

如果你不确定它是否是一个 list,一个numpy数组,或其他东西,你可以结合这种方法 答案@dubiousjim给出 确保为每种类型使用正确的测试。不是很“pythonic”,但事实证明numpy至少在这个意义上有意破坏了pythonicity。

如果您需要做的不仅仅是检查输入是否为空,并且您正在使用索引或数学运算等其他numpy功能,那么强制输入可能更有效(当然也更常见) 成为 一个numpy数组。快速完成这项工作有一些很好的功能 - 最重要的是 numpy.asarray。这会接受你的输入,如果它已经是一个数组就什么都不做,或者如果它是一个列表,元组等,你的输入就会包装成一个数组,并且可以选择将它转换成你选择的 dtype。所以只要它可以很快,它确保你只是假设输入是一个numpy数组。我们通常甚至只使用相同的名称,因为转换为数组不会使其回到当前的范围之外 范围

x = numpy.asarray(x, dtype=numpy.double)

这将使 x.size 检查我在本页看到的所有情况下的工作。


209
2018-02-21 16:48



值得注意的是,这不是Python的一个缺陷,而是故意违约 numpy  - numpy 是一个具有非常特定用例的库,它对数组的真实性与容器的Python标准有不同的“自然”定义。以这种方式对这种情况进行优化是有意义的 pathlib 使用 / 连接路径而不是 +  - 它是非标准的,但在上下文中是有意义的。 - Gareth Latty
同意。我的观点是,重要的是要记住numpy已经选择打破常见的鸭子打字 if x 和 len(x) 习语 - 有时候破坏可能很难检测和调试。 - Mike
我不知道,对于我来说,如果一个名为len(x)的方法因为假设而没有返回数组长度,那么它的名字设计不好。 - Dalton
这个问题与numpy数组无关 - ppperry
@ppperry是的,最初的问题不是关于Numpy数组,但是当使用那些并且可能是鸭子类型的参数时,这个问题变得非常相关。 - peterhil


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

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

@Daren Thomas

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

你的duckCollection应该实现 __nonzero__ 要么 __len__ 所以如果a:将没有问题。


104
2017-09-10 06:31





检查列表是否为空的最佳方法

例如,如果传递以下内容:

a = []

如何检查a是否为空?

简答:

将列表放在布尔上下文中(例如,使用 if 要么 while 声明)。它会测试 False 如果它是空的,和 True 除此以外。例如:

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

上诉到权威

PEP 8,Python标准库中Python代码的官方Python风格指南断言:

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

Yes: if not seq:
     if seq:

No: if len(seq):
    if not 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中甚至在语义上也是正确的。

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

来自 文档 (并特别注意列入空列表, []):

默认情况下,除非其类定义,否则将对象视为true   要么a __bool__() 返回的方法 False 或者a __len__() 方法   当使用对象调用时返回零。以下是大多数被认为是错误的内置对象:

  • 常量定义为false: None 和 False
  • 任何数字类型的零: 00.00jDecimal(0)Fraction(0, 1)
  • 空序列和集合: ''()[]{}set()range(0)

和datamodel文档:

object.__bool__(self)

被称为实施真值测试和内置操作 bool();应该回来 False 要么 True。如果未定义此方法,    __len__() 如果已定义,则调用该对象,如果其结果为非零,则将该对象视为true。如果一个类都没有定义 __len__()   也不 __bool__(),它的所有实例都被认为是真实的。

object.__len__(self)

被称为实现内置功能 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

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

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

我们看到了  使用内置函数检查长度 len 相比 0  要么 检查空列表是 许多 与使用所记录的语言的内置语法相比,性能较差。

为什么?

为了 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 宏。

来自c源 包含/ listobject.h

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

我很喜欢研究这个,我花了很多时间来策划我的答案。如果您认为我要留下一些东西,请在评论中告诉我。


83
2017-08-20 03:50



这是IMO非常好的阅读和一个有价值的贡献(在提出问题九年后作出回应可能有一些气味,但至少对我来说不是这种情况)。谢谢亚伦。 - Dilettant
@Dilettant气味是经验法则或启发式,让我们看得更近。一些新用户发布了迟到的答案,基本上复制了其他答案,这就是我们在迟到答案时所关注的事情。迟到的答案增加了价值 是 但是非常受欢迎 - 否则我们会在一段时间后关闭帖子,就像Reddit那样。 - Aaron Hall♦


帕特里克(接受)答案 是对的: if not a: 是正确的方法。 哈利霍尔科姆的答案 是的,这是PEP 8风格指南。但是,没有任何答案可以解释为什么遵循这个习惯是一个好主意 - 即使你个人发现它不够明确或者对Ruby用户或其他任何东西感到困惑。

Python代码和Python社区有很强的习惯用法。遵循这些习语使得使用Python的任何人都可以更轻松地阅读代码。当你违反这些习语时,这是一个强烈的信号。

这是真的 if not a: 不区分空列表 None,或数字0,或空元组,或空的用户创建的集合类型,或空的用户创建的非完全集合类型,或单元素NumPy数组充当具有假值的标量等。有时它是重要的是明确的。在那种情况下,你知道 什么 你想要明确,所以你可以测试它。例如, if not a and a is not None:意思是“任何虚假的,除了无”,而 if len(a) != 0: 意味着“只有空序列 - 除了序列之外的任何东西都是错误的”,依此类推。除了测试您想要测试的内容外,这也向读者发出此测试很重要的信号。

但是当你没有任何明确的东西时,除了 if not a: 误导了读者。当事实并非重要时,你就会发出重要的信号。 (你可能也会使代码变得不那么灵活,或者更慢,或者其他什么,但这些都不那么重要。)如果你 习惯性地 像这样误导读者,然后当你  需要做出区分,它会被忽视,因为你在你的代码中一直在“哭狼”。


82
2017-12-03 02:21





我已经看到以下是首选:

if not a:
    print("The list is empty or null")

63
2017-09-10 06:28



None 不是一个清单;它是自己的类型。 - Yann Vernier


为什么要检查?

似乎没有人质疑你的问题 需要 首先测试列表。因为您没有提供额外的上下文,我可以想象您可能不需要首先进行此检查,但不熟悉Python中的列表处理。

我会争辩说 大多数pythonic 方式是根本不检查,而是只处理列表。这样,无论是空的还是满的,它都会做正确的事情。

a = []

for item in a:
    <do something with item>

<rest of code>

这有利于处理任何内容 一个,虽然不需要特别检查空虚。如果 一个 为空,依赖块将不会执行,解释器将进入下一行。

如果你确实需要检查数组是否空虚,那么其他答案就足够了。


53
2017-10-06 19:25



问题是,检查列表是否为空是非常重要的,至少对我而言。你有没有考虑过里面是否有一些脚本 <rest of code> 可能会使用结果 for 循环?或者直接使用一些值 a?实际上,如果脚本设计为使用严格控制的输入运行,则检查可能有点不必要。但在大多数情况下,输入会有所不同,检查通常会更好。 - Amarth Gûl
在大多数情况下,这是一个好点 - jamylak
恭敬地,没有。我所考虑的是一个对Python不够了解的人知道“if <list>:”是正确的答案,询问如何检查一个空列表。然后我注意到很多答案提供了不同的意见,但似乎没有一个解决原来的需要。这就是我试着用我的答案做的 - 让他们在继续之前检查需要。我相信我明确地在答案中提出了建议。 - MrWonderful
@AmarthGûl - 怎么可能 得到 for循环到<rest of code>里面的脚本的结果要处理?也许在列表中?或者也许是一个词典?如果是这样,则适用相同的逻辑。我不明白怎么做 变量输入 可以在任何类型的合理设计的代码中产生任何影响,处理空列表将是一个坏主意。 - MrWonderful