当前位置:  开发笔记 > 编程语言 > 正文

如何检查列表是否为空?

如何解决《如何检查列表是否为空?》经验,为你挑选了17个好方法。

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

a = []

如何检查是否a为空?



1> Patrick..:
if not a:
  print("List is empty")

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


扮演魔鬼的拥护者.我不明白为什么这个成语被认为是pythonic.'明确比隐含更好',对吗?关于检查的内容,此检查似乎并不十分明确.
@JamesMcMahon - 它是显性和类型灵活性之间的权衡.一般来说,"明确"意味着不做"神奇"的事情.另一方面,"duck typing"意味着使用更通用的接口,而不是显式检查类型.所以像`if a == []`强制特定类型(`()== []`是'False`).在这里,普遍的共识似乎是鸭子打字胜出(实际上,说`__nonzero__`是测试空虚的界面http://docs.python.org/reference/datamodel.html#object.__nonzero__)
此方法不适用于numpy数组。.因此,我认为就duck类型和隐式而言,如果len(a)== 0更好。
知道C中的数组是否为空的规范方法是,通过取消引用第一个元素并查看其是否为空,并假定数组为nul终止。否则,如果数组的大小很大,则将其长度与零进行比较是完全无效的。同样,通常,您不会为空数组分配内存(指针保持为空),因此尝试获取其长度没有任何意义。我并不是说len(a)== 0并不是一个好方法,当我看到它时,它并没有向我尖叫'C'。
@BrennenSprimont,如果它不是以Null结尾的,那么您已经知道了长度,无论是将其存储在单独的变量中还是将数组包装在一些跟踪该长度的容器中。C ++,Java,C#具有此类容器并有效地实现某些“长度”方法。C *没有这样的*,您必须自己动手。静态分配的C数组只是指向内存空间的指针,该内存空间保证有足够的空间来存储您请求的数据量。C中没有内置任何东西可以让您知道已经填充了多少空间。

2> Harley Holco..:

pythonic方法是从PEP 8样式指南(其中Yes表示"推荐",No表示"不推荐"):

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

Yes: if not seq:
     if seq:

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


第二种方式似乎更好,如果你想发出'seq`预计是某种类似列表的对象的信号.
@BallpointBen尝试使用Python的[类型提示](https://docs.python.org/3/library/typing.html)来表示变量应该是什么。它是在3.5中引入的。
numpy打破了这种习惯用法... seq = numpy.array([1,2,3]),如果不是seq,则会引发异常“ ValueError:具有多个元素的数组的真值不明确。请使用a.any ()或a.all()”
Python主张所说的@BallpointBen应尽可能隐含在变量的命名方式中

3> Jabba..:

我明确地喜欢它:

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

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


检查列表的长度是否等于零,而不仅仅是检查列表是否为假,是丑陋和单一的.任何熟悉Python的人都不会认为`li`根本就不是bool,也不会在乎.如果它很重要,您应该添加注释,而不是更多代码.
无论如何,这是坏的原因(并且在一般语言中使用像Python这样的强大成语的语言中违反成语)是因为它向读者发出信号,指出你是出于某种原因专门检查长度的(例如,因为你想要`无`或'0`引发异常而不是传递.所以,当你无缘无故地这样做时,那就是误导 - 而且这也意味着当你的代码_does_需要进行区分时,这种区别是不可见的,因为你已经在所有其他来源中"狼来了".
我认为这只是不必要地延长了代码.否则,如果bool(len(li)== 0)为真,为什么不能更"明确":`?
这似乎是一个不必要的精确测试,通常较慢,并且总是不太可读恕我直言.而不是检查空的大小,为什么不检查它是否为空?
@Jabba在许多情况下(使用内置数据类型的那些)将是**O(1)**,但你不能依赖它.您可能正在使用没有此属性的自定义数据类型.在您编写此代码之后,您可能还决定稍后添加此自定义数据类型.
抓住长度只是为了检查空虚是非常糟糕的.这在任何方面都不好.
这是反PEP 8
如果你*做*想要为没有`__len__`的类型引发异常怎么办?在这种情况下,这是完美的.
如果不清楚`li`是一个列表,也许您不应该将其命名为`li`。我认为只有两个字母的好的变量名很少。那“汽车”或“逃避_操纵”呢?另一方面,布尔值的名称中应带有“ is”或“ has”或其他动词,并比较“ if is_evasive_manoeuvre:”和“ ifevasive_maoeuvres”。对我来说很明显,哪个是布尔值,哪个是集合。

4> Mike..:

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

其他方法不适用于numpy数组

您需要小心numpy数组,因为其他适用于lists或其他标准容器的方法对于numpy数组都会失败.我在下面解释原因,但简而言之,首选方法是使用size.

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

"pythonic"方式因numpy数组失败,因为numpy尝试将数组转换为bools 数组,并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,即使数组元素为零.

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

如果您不确定它是否是a list,numpy数组或其他什么,您可以将此方法与@dubiousjim给出的答案结合起来,以确保为每种类型使用正确的测试.不是很"pythonic",但事实证明numpy至少在这个意义上有意破坏了pythonicity.

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

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

这将使x.size检查在我在此页面上看到的所有情况下都能正常工作.


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

5> Aaron Hall..:

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

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

a = []

如何检查a是否为空?

简答:

将列表放在布尔上下文中(例如,使用ifwhile语句).它将测试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,除非其类定义__bool__()返回False__len__()方法或返回零的方法(使用对象调用时).以下是大多数被认为是错误的内置对象:

常量定义为false:NoneFalse.

任何数值类型的零:0,0.0,0j,Decimal(0),Fraction(0, 1)

空序列和集合:'',(),[],{},set(),range(0)

和datamodel文档:

object.__bool__(self)

被称为实施真值测试和内置操作bool(); 应该回来FalseTrue.如果未定义此方法,__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宏扩展定义的字段.

从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

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



6> Peter Hoffma..:

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

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

@Daren Thomas

编辑:反对测试空列表的另一点是错误的:多态性怎么样?您不应该依赖列表作为列表.它应该像鸭子一样嘎嘎叫 - 如果它没有元素,你怎么能让你的duckCollection嘎嘎''假''?

你的duckCollection应该实现,__nonzero__或者__len__if a:将正常工作.



7> abarnert..:

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

Python代码和Python社区有很强的习惯用法.遵循这些习语使得您的代码更易于阅读Python中的任何人.当你违反这些习语时,这是一个强烈的信号.

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

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



8> MrWonderful..:
为什么要检查?

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

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

a = []

for item in a:
    


这具有处理任何内容的好处,而不是要求对空虚的特定检查.如果a为空,则依赖块将不会执行,解释器将进入下一行.

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


问题是,至少对于我来说,检查列表是否为空非常重要。您是否考虑过“ <其余代码>”中是否有一些脚本可能会使用“ for”循环的结果?还是直接在`a`中使用某些值?确实,如果脚本被设计为在严格控制的输入下运行,则检查可能是不必要的。但是在大多数情况下,输入会有所不同,通常进行检查会更好。
@DJK-不,我想您仍然想念它。如果您有一个清单,想必您想用清单来做某事。如果它是空的,您会怎么做?早点回来?如果不为空怎么办?处理吗?关键仍然是,您不必检查空列表,只需对其进行迭代,然后对元素进行任何处理即可。如果没有任何元素,您就会失败。如果有元素,则可以根据需要对其进行处理。重点不是使用示例进行空检查,而是根本不检查,只需处理列表即可。

9> George V. Re..:

len()是 Python列表,字符串,dicts和集合的O(1)操作.Python内部跟踪这些容器中的元素数量.

JavaScript 有一个类似于truthy/falsy的概念.



10> dubiousjim..:

我写过:

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

被选为-1.我不确定是不是因为读者反对这个策略或者认为答案没有提供帮助.我会假装它是后者,因为---无论什么都算"pythonic" - 这是正确的策略.除非你已经排除,或者准备好处理a例如情况,否则False你需要一个比仅仅更严格的测试if not a:.你可以使用这样的东西:

if isinstance(a, numpy.ndarray) and not a.size:
    do_stuff
elif 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是周围的上下文已经向你保证这是你准备处理的类型的值,或者如果你确定那些你不准备处理的类型正在进行中提出你准备处理的错误(例如,TypeError如果你调用len一个未定义的值).一般来说,"pythonic"惯例似乎是最后一种方式.像鸭子一样挤压它,如果它不知道如何嘎嘎,就让它引发一个DuckError.你仍然需要考虑你正在做什么类型的假设,以及你不准备正确处理的案例是否真的会在正确的地方出错.Numpy数组是一个很好的例子,只是盲目依赖len或布尔类型转换可能无法完全按照您的期望.


人们不喜欢这样做的原因是因为在大多数情况下它完全没有问题.Python是一种鸭式语言,这种级别的防御性编码主动阻碍了这种情况.Python类型系统背后的想法是,只要对象以所需的方式传递给函数,事情就应该有效.通过执行显式类型检查,您强制调用者使用特定类型,违背语言的要求.虽然有时候这些事情是必要的(排除字符串不被视为序列),但这种情况很少见,并且几乎总是最好的黑名单.
很少有你想要接受的6种类型的详尽列表,而且对于任何其他类型都不灵活.当你需要那种东西时,你可能想要一个ABC.在这种情况下,它可能是stdlib ABCs之一,如`collections.abc.Sized`或`collections.abc.Sequence`,但它可能是你自己写的`和register(list)`on.如果你真的有代码来区分空虚与其他虚假,以及将列表和元组与任何其他序列区分开来,那么这是正确的 - 但我不相信你有这样的代码.
但是`==`有一些自动强制.在我的头顶,我无法识别出任何"[]`.`[] ==()`例如返回`False`.但是例如`frozenset()== set()`返回'True`.因此,至少可以考虑一下在执行`a == []`时是否会将某些不需要的类型强制转换为`[]`(反之亦然).

11> Sнаđошƒаӽ..:

从关于真值测试的文档:

除此处列出的值之外的所有值都将被考虑 True

None

False

任何数字类型,例如零,0,0.0,0j.

任何空序列,例如'',(),[].

例如,任何空映射{}.

用户定义的类的实例,如果类定义了一个__bool__()__len__()方法,则该方法返回整数零或bool值False.

可以看出,空列表[]假的,因此对布尔值执行的操作听起来效率最高:

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



12> Inconnu..:

您可以通过以下几种方法检查列表是否为空:

a = [] #the list

1)非常简单的pythonic方式:

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

在Python中,列表,元组,集合,dicts,变量等空容器被视为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 elements
except StopIteration:
    print("Error: a is empty")



13> 小智..:

方法1(首选):

if not a : 
   print ("Empty") 

方法2:

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

方法3:

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



14> verix..:

我更喜欢以下内容:

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


这将变得更慢,因为您不必要地实例化一个额外的空列表.
这比`if not a:`更不易读,而且更容易破解.请不要这样做.

15> Tagar..:
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 None 
list is empty 
list 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 empty
list is empty
list has 3 elements



16> 小智..:

给出了许多答案,其中很多都很好。我只想补充一下

not a

也将通过None和其他类型的空结构。如果您确实要检查一个空列表,可以执行以下操作:

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


@SvenKrüger不。运算符`and`在Python中很懒。如果`and`之前的条件为False,则不会执行`and`之后的任何操作。

17> 小智..:

我们可以使用简单的方法:

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


-1-为避免混淆,请不要在变量名中使用保留字,否则下次尝试调用时可能会出现令人惊讶的行为,例如“ list()”……类似于“ TypeError:'list'object is不可通话”或类似的内容。
推荐阅读
kikokikolove
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有