如何检查列表是否为空?

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

a = []

如何检查a是否为空?

4423937 次浏览
if not a:print("List is empty")

使用空的list隐含布尔性是相当Pythonic的。

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

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

达伦·托马斯的回答

编辑:反对测试的另一个观点空列表为假:关于多态?你不应该依赖列表就是列表。它应该像鸭子一样嘎嘎叫-你好吗让你的鸭子收藏嘎嘎叫“假”当它没有元素时?

您的DUKCollection应该实现__nonzero____len__,这样if a:就可以正常工作。

我更喜欢以下内容:

if a == []:print "The list is empty."

Pythonic的方法是从PEP 8风格指南开始的。

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

# Correct:if not seq:if seq:
# Wrong:if len(seq):if not len(seq):

#0是一个O(1)操作用于Python列表、字符串、字典和集合。Python在内部跟踪这些容器中的元素数量。

JavaScript有类似的真假概念.

我更喜欢它明确:

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

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

这是谷歌第一次针对“python测试空数组”和类似的查询,其他人正在将这个问题推广到列表之外,所以这里有一个警告,针对很多人使用的不同类型的序列。

其他方法不适用于NumPy数组

您需要小心NumPy数组,因为其他适用于list或其他标准容器的方法在NumPy数组中失败。我在下面解释了原因,但简而言之,优选方法是使用size

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

NumPy数组的“pythonic”方式失败了,因为NumPy试图将数组转换为一个包含bool的数组,而if x试图一次评估所有这些bool以获得某种聚合真值。但这没有任何意义,所以你得到一个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,即使数组的元素为零。

用数字的方式

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数组可能更有效(当然也更常见)。有一些很好的函数可以快速执行此操作-最重要的是#0。这接受你的输入,如果它已经是一个数组,则不执行任何操作,或者如果它是一个列表,元组等,则将你的输入包装到一个数组中,并可选择将其转换为你选择的dtype。所以它非常快,只要它可以,它可以确保你只是假设输入是一个NumPy数组。我们通常甚至只使用相同的名称,因为转换为数组不会使其回到当前范围之外:

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

这将使x.size检查在我在此页面上看到的所有情况下都有效。

我曾写过:

if isinstance(a, (list, some, other, types, i, accept)) and not a:do_stuff

结果为-1。我不确定这是因为读者反对这个策略,还是认为答案没有像呈现的那样有帮助。我会假装是后者,因为——不管怎么说都是“pythonic”——这是正确的策略。除非你已经排除了,或者准备处理aFalse的情况,否则你需要一个比if not a:更具限制性的测试。你可以使用这样的东西:

if isinstance(a, numpy.ndarray) and not a.size:do_stuffelif isinstance(a, collections.Sized) and not a:do_stuff

第一个测试是对@Mike的回答的回应,上面。第三行也可以替换为:

elif isinstance(a, (list, tuple)) and not a:

如果您只想接受特定类型(及其子类型)的实例,或者使用:

elif isinstance(a, (list, tuple)) and not len(a):

你可以不进行显式类型检查,但前提是周围的上下文已经向你保证a是你准备处理的类型的值,或者如果你确定你不准备处理的类型会引发你准备处理的错误(例如,如果你在一个未定义的值上调用len,则为TypeError)。一般来说,“pythonic”约定似乎走到了最后一条路。像鸭子一样挤压它,如果它不知道如何嘎嘎叫,让它引发DuckError。但是,你仍然需要认为关于你正在做的类型假设,以及你没有准备好正确处理的情况是否真的会在正确的地方出错。Numpy数组是一个很好的例子,盲目地依赖len或布尔类型转换可能不会完全达到你的预期。

帕特里克(接受)的回答是对的:if not a:是正确的方法。Harley Holcombe的回答是对的,这是在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:之外的任何东西都会误导读者。当你不重要的时候,你在发出同样重要的信号。(你也可能会让代码变得不那么灵活,或者更慢,或者其他什么,但这一切都不那么重要。)如果你习惯性地这样误导读者,那么当你需要做出区分的时候,它就会被忽视,因为你的代码到处都是“狼来了”。

为什么要检查?

似乎没有人首先解决了质疑你的需要来测试列表的问题。因为你没有提供额外的上下文,我可以想象你可能一开始就不需要做这个检查,但不熟悉Python中的列表处理。

我认为最Pythonic的方法是根本不检查,而只是处理列表。这样它就会做正确的事情,无论是空的还是满的。

a = []
for item in a:# <Do something with item>
# <The rest of code>

这样做的好处是可以处理一个的任何内容,同时不需要特定的空洞检查。如果一个为空,依赖块将不执行,解释器将进入下一行。

如果您确实需要检查数组是否为空:

a = []
if not a:# <React to empty list>
# <The rest of code>

就足够了。

留档关于真值测试:

除了这里列出的所有值都被认为是True

  • None
  • False
  • 任何数字类型的零,例如00.00j
  • 任何空序列,例如''()[]
  • 任何空映射,例如{}
  • 用户定义类的实例,如果类定义了__bool__()__len__()方法,当该方法返回整数零或bool值False时。

可以看出,空列表[]Falsy,所以对布尔值做什么听起来最有效:

if not a:print('"a" is empty!')
def list_test (L):if   L is None  : print('list is None')elif not L      : print('list is empty')else: print('list has %d elements' % len(L))
list_test(None)list_test([])list_test([1,2,3])

有时单独测试None和空是很好的,因为这是两种不同的状态。上面的代码产生以下输出:

list is Nonelist is emptylist has 3 elements

尽管None是错误的毫无价值。所以如果你不想为None-ness分开测试,你不必这样做。

def list_test2 (L):if not L      : print('list is empty')else: print('list has %d elements' % len(L))
list_test2(None)list_test2([])list_test2([1,2,3])

产生预期

list is emptylist is emptylist has 3 elements

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

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

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

非常方便和有用。

以下是检查列表是否为空的几种方法:

a = [] #the list

1)非常简单的pythonic方式:

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

在Python中,空容器(例如列表、元组、集合、字典、变量等)被视为False。人们可以简单地将列表视为谓词(返回一个布尔值)。True值将表明它是非空的。

2)一个非常明确的方法:使用len()来查找长度并检查它是否等于0

if len(a) == 0:print("a is empty")

3)或者将其与匿名空列表进行比较:

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

4)另一种愚蠢方法是使用exceptioniter()

try:next(iter(a))# list has elementsexcept StopIteration:print("Error: a is empty")

受到dubiousjim解的启发,我建议使用额外的一般检查来检查它是否是可迭代的:

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

注意:字符串被认为是可迭代的-如果您希望排除空字符串,请添加and not 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是否为空?

简短回答:

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

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

PEP 8

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,除非它的类定义了返回False__bool__()方法或__len__()方法当与对象一起调用时,返回零。以下是大多数被认为是false的内置对象:

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

和datamodel留档:

object.__bool__(self)

调用以实现真值测试,内置操作bool();应该返回FalseTrue。当未定义此方法时,如果定义了__len__(),则调用它,如果结果非零,则该对象被视为true。如果一个类既没有定义__len__()也不是__bool__(),它的所有实例都被认为是true。

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是否被阴影。

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

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

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

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

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

>>> dis.dis(lambda: not [])1           0 BUILD_LIST               02 UNARY_NOT4 RETURN_VALUE

来自C源和留档的证据

PyVarObject

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

包含/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=[]然后%timeit len(l) != 0 90.6 ns±8.3 ns,%timeit l != [] 55.6 ns±3.09,%timeit not not l 38.5 ns±0.372。但是,尽管速度增加了三倍,但没有人会喜欢not not l。它看起来很荒谬。但是速度胜出了
我想问题是测试时间,因为只有if l:就足够了,但令人惊讶的是%timeit bool(l)产生101 ns±2.64 ns。有趣的是,没有这种惩罚就没有办法强制bool。%timeit l是无用的,因为不会发生转换。

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

In [1]: l = []
In [2]: %timeit l20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
In [3]: %timeit not l24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [4]: %timeit not not l30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

我们可以看到这里每个额外的not都有一点线性成本。我们希望看到成本,其他条件不变,即其他一切相等-其中所有其他都尽可能最小化:

In [5]: %timeit if l: pass22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [6]: %timeit if not l: pass24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [7]: %timeit if not not l: pass23.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: pass23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [10]: %timeit if not l: pass23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [11]: %timeit if not not l: pass26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

我们可以在这里看到的是,无论您将实际的bool传递给条件检查还是列表本身,都没有什么区别,如果有的话,按原样给出列表更快。

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

只需使用is_empty()或使函数如下:-

def is_empty(any_structure):if any_structure:print('Structure is not empty.')return Trueelse:print('Structure is empty.')return False

它可以用于任何data_structure,如列表、元组、字典等等。通过这些,您可以使用is_empty(any_structure)多次调用它。

如果要检查列表是否为空:

l = []if l:# do your stuff.

如果要检查列表中的所有值是否为空。但是对于空列表,它将是True

l = ["", False, 0, '', [], {}, ()]if all(bool(x) for x in l):# do your stuff.

如果您想同时使用这两种情况:

def empty_list(lst):if len(lst) == 0:return Falseelse:return all(bool(x) for x in l)

现在您可以使用:

if empty_list(lst):# do your stuff.

空列表的真值是False,而非空列表的真值是True

简单的方法是检查长度是否等于零。

if len(a) == 0:print("a is empty")

已经给出了很多答案,其中很多都非常好。我只是想补充一下

not a

也将传递None和其他类型的空结构。如果你真的想检查一个空列表,你可以这样做:

if isinstance(a, list) and len(a)==0:print("Received an empty list")
print('not empty' if a else 'empty')

稍微实际一点:

a.pop() if a else None

最短的版本:

if a: a.pop()

从python3开始,您可以使用

a == []

检查列表是否为空

编辑:这也适用于python2.7。

我不知道为什么有这么多复杂的答案。很简单很简单

要检查列表是否为空,您可以使用以下两种方法。但请记住,我们应该避免显式检查序列类型的方式(这是少Pythonic方式):

def enquiry(list1):return len(list1) == 0
# ––––––––––––––––––––––––––––––––
list1 = []
if enquiry(list1):print("The list isn't empty")else:print("The list is Empty")
# Result: "The list is Empty".

第二种方法是更多Pythonic方法。这种方法是一种隐式检查方法,比前一种方法更可取。

def enquiry(list1):return not list1
# ––––––––––––––––––––––––––––––––
list1 = []
if enquiry(list1):print("The list is Empty")else:print("The list isn't empty")
# Result: "The list is Empty"

我们可以使用简单的如果有的话

item_list=[]if len(item_list) == 0:print("list is empty")else:print("list is not empty")

方法1(首选):

if not a:print ("Empty")

方法二:

if len(a) == 0:print("Empty")

方法三:

if a == []:print ("Empty")

把我带到这里的是一个特殊的用例:我实际上想要一个函数来告诉我列表是否为空。我想避免在这里编写自己的函数或使用lambda表达式(因为它看起来应该足够简单):

foo = itertools.takewhile(is_not_empty, (f(x) for x in itertools.count(1)))

当然,有一种非常自然的方法可以做到这一点:

foo = itertools.takewhile(bool, (f(x) for x in itertools.count(1)))

当然,没有if(即if bool(L):)中使用bool是因为它是隐含的。但是,对于明确需要“不为空”作为函数的情况,bool是最佳选择。