如何检查列表是否为空?

How do I check if a list is empty?

提问人:Ray 提问时间:9/10/2008 最后编辑:ayhanRay 更新时间:2/15/2023 访问量:4743428

问:

这个问题的答案是社区的努力。编辑现有答案以改进此帖子。它目前不接受新的答案或互动。

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

a = []

如何检查是否为空?a

python 列表

评论


答:

7096赞 Patrick 9/10/2008 #1
if not a:
    print("List is empty")

使用空的隐式布尔值是相当 Python 的。list

评论

1531赞 James McMahon 11/22/2011
扮演魔鬼的拥护者。我不明白为什么这个成语被认为是pythonic。“显式比隐式更好”,对吗?这种检查似乎对正在检查的内容不是很明确。
283赞 andrew cooke 5/31/2012
@JamesMcMahon - 这是显式性和类型灵活性之间的权衡。一般来说,“露骨”意味着不做“神奇”的事情。另一方面,“鸭子类型”意味着使用更通用的接口,而不是显式检查类型。所以像这样的东西是强制一个特定的类型( 是 )。在这里,普遍的共识似乎是鸭子打字胜出(实际上,说这是测试空性的接口 docs.python.org/reference/datamodel.html#object.__nonzero__if a == []() == []False__nonzero__)
124赞 Mr.WorshipMe 3/21/2019
此方法不适用于 numpy 数组。.所以我认为如果 len(a) == 0 在“鸭子类型”和隐式方面都是可取的。
12赞 Brennen Sprimont 4/14/2019
@sleblanc除了实现字符串之外,我从未在 c 中看到过 null 终止数组,常见的情况是不是 null 终止。“将其长度与零进行比较是完全低效的”是不正确的,不存在 C 实现,这将花费超过几个周期。将数组的长度与 0 进行比较以确定空虚是 c 和几乎所有受 c 影响的语言(c++、java、c# 等)的标准做法。
105赞 Edwin Rodríguez 4/4/2020
这种机制来自一种自称是某种诗歌的语言,纯粹是垃圾。从语义上讲,空与空与不空有很大不同
179赞 Peter Hoffmann 9/10/2008 #2

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

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

对于Daren Thomas的回答

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

你的 duckCollection 应该实现 if a: 可以毫无问题地工作。__nonzero____len__

评论

2赞 information_interchange 10/14/2019
奇怪的是,如何评估为假[] == False
7赞 augurar 10/20/2019
@information_interchange 如果要显式检查值的真实性,请使用 . 将按预期进行评估。bool()bool([]) == FalseTrue
1赞 Paul 6/9/2022
@information_interchange 其实不然。考虑一下,如果计算到那时,为了保持一致性,也应该和 ,甚至 .请注意,布尔上下文中的真实性和测试相等性是有区别的。恕我直言,Clojure 做对了:只有 False 和 nil 是虚假的。Python 的规则是合理的。PHP曾经有邪恶的规则(很久没有使用过了,现在不知道)。[] == FalseTrue0 == False'' == False'' == []
37赞 verix 9/10/2008 #3

我更喜欢以下几点:

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

评论

52赞 Carl Meyer 9/10/2008
这会变慢,因为您不必要地实例化了一个额外的空列表。
43赞 devsnd 11/12/2012
这比可读性更差,也更容易中断。请不要这样做。if not a:
0赞 A Star 3/17/2019
前面说的一个很好的观点也等于错误。虽然我喜欢这个实现如何读取涵盖所有情况,但如果你肯定期待一个列表,那么你的示例应该就足够了。() == []if not a:
8赞 scubbo 8/21/2020
需要“更容易打破”引用吗? 当 a is 时中断 - 您可能希望 和 具有相同的行为,但如果您明确想要检查空列表,则不会这样做。if not aNoneNone[]if not a
1赞 AboodXD 4/22/2021
@scubbo,如果您真的想显式检查它是否是空列表,请考虑改用。isinstance(a, list) and not a
1490赞 Harley Holcombe 9/10/2008 #4

Python 的方法是来自 PEP 8 风格指南

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

# Correct:
if not seq:
if seq:

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

评论

126赞 BallpointBen 5/11/2018
如果您希望发出信号,则第二种方法似乎更好,该信号应为某种类似列表的对象。seq
21赞 axolotl 7/14/2018
Pythonism 的拥护者会说,@BallpointBen应该尽可能地隐含在变量的命名方式中
14赞 1/5/2019
@BallpointBen尝试使用 Python 的类型提示来指示变量应该是什么。它是在 3.5 中引入的。
20赞 Mr.WorshipMe 3/21/2019
numpy打破了这个成语......seq = numpy.array([1,2,3]) 后跟 if not seq 引发异常 “ValueError: The truth value value of a multiple element is ambiguous.使用 a.any() 或 a.all()”
19赞 aafulei 9/26/2019
尽管有所有 Python 的拥护者,但我@BallpointBen,如果你错误地写成 ,将帮助你发现错误。犯错是人之常情。程序员也是如此。seq = [0]seq = 0len(seq)
76赞 George V. Reilly 9/15/2008 #5

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

JavaScript 也有类似的真实/虚假概念

1096赞 Jabba 9/5/2011 #6

我明确地更喜欢它:

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

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

评论

135赞 Carl Smith 7/9/2013
检查列表的长度是否等于零,而不仅仅是检查列表是否为假,是丑陋且不合时宜的。任何熟悉 Python 的人都不会认为这是一个布尔,也不会在乎。如果它很重要,你应该添加一个注释,而不是更多的代码。li
33赞 John B 6/23/2014
这似乎是一个不必要的精确测试,恕我直言,它通常较慢且总是可读性较差。与其检查空的东西的大小,为什么不直接检查它是否是空的呢?
48赞 abarnert 12/3/2014
无论如何,这很糟糕的原因(在像 Python 这样具有强习惯语的语言中违反习语通常是不好的)是它向读者发出信号,表明您出于某种原因(例如,因为您想要或引发异常而不是传递)。所以,当你无缘无故地这样做时,这是误导性的——这也意味着当你的代码确实需要区分时,这种区分是看不见的,因为你已经在源代码的其余部分“哭狼嚎”了。None0
33赞 augurar 1/6/2015
我认为这只是不必要地延长代码。否则,为什么不更“明确”呢?if bool(len(li) == 0) is True:
17赞 ralokt 11/19/2015
@Jabba在许多情况下,它将是 O(1)(那些使用内置数据类型的情况),但你不能依赖它。您可能正在使用没有此属性的自定义数据类型。在编写此代码之后,您可能还决定稍后添加此自定义数据类型。
421赞 Mike 2/22/2012 #7

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

其他方法不适用于 NumPy 数组

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

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

“pythonic”方式在 NumPy 数组中失败,因为 NumPy 试图将数组转换为 s 数组,并尝试一次评估所有这些 s 以获得某种聚合真值。但这没有任何意义,所以你会得到一个:boolif xboolValueError

>>> 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 数组,那么该语句将“工作”,从某种意义上说,你不会得到错误。但是,如果该元素恰好是 (或 , 或 , ...),则该语句将错误地导致:if00.0FalseifFalse

>>> 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

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

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

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

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

评论

90赞 Gareth Latty 2/17/2015
值得注意的是,这不是 Python 中的缺陷,而是故意破坏契约的 - 是一个具有非常特定用例的库,并且它对数组的真实性有不同的“自然”定义与容器的 Python 标准。针对这种情况进行优化是有意义的,以用于连接路径而不是 - 的方式是非标准的,但在上下文中是有意义的。numpynumpypathlib/+
14赞 Mike 2/17/2015
同意。我的观点是,重要的是要记住,numpy 已经选择破坏非常常见和习语的鸭子类型——有时这种破坏可能很难检测和调试。if xlen(x)
30赞 Dalton 8/21/2015
我不知道,对我来说,如果一个名为 len(x) 的方法因为假设而不返回数组长度,它的名字设计得很糟糕。
15赞 pppery 8/1/2017
这个问题与numpy数组无关
33赞 peterhil 9/13/2017
@ppperry 是的,最初的问题不是关于 Numpy 数组,但是当使用这些参数以及可能的 duck 类型参数时,这个问题变得非常相关。
53赞 dubiousjim 5/31/2012 #8

我曾写过:

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

投票结果为-1。我不确定这是因为读者反对该策略还是认为答案没有帮助。我会假装是后者,因为---无论什么都算作“pythonic”---这是正确的策略。除非您已经排除了,或者准备处理以下情况,例如,您需要一个比 .你可以使用这样的东西:aFalseif 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):

你可以在没有显式类型检查的情况下逃脱,但前提是周围的上下文已经向你保证这是你准备处理的类型的值,或者你确定你不准备处理的类型会引发错误(例如,如果你调用了一个未定义的值),你准备处理。一般来说,“pythonic”约定似乎是最后一种方式。像鸭子一样挤压它,如果它不知道如何嘎嘎叫,就让它发出 DuckError。但是,您仍然必须考虑您正在做出什么类型的假设,以及您没有准备好正确处理的案例是否真的会在正确的地方出错。Numpy 数组就是一个很好的例子,仅仅盲目地依赖或布尔类型转换可能无法完全达到您的期望。aTypeErrorlenlen

评论

3赞 abarnert 12/3/2014
您很少会有一个详尽的 6 种类型列表,您想要接受这些类型,并且对任何其他类型的类型都不灵活。当你需要这种东西时,你可能想要一个ABC。在这种情况下,它可能是 stdlib ABC 之一,比如 或 ,但它可能是你自己写的。如果你确实有代码,其中区分空和其他错误很重要,并且还需要将列表和元组与任何其他序列区分开来,那么这是正确的——但我不相信你有这样的代码。collections.abc.Sizedcollections.abc.Sequenceregister(list)
14赞 Gareth Latty 2/17/2015
人们不喜欢这样做的原因是,在大多数情况下,它完全是不正常的。Python 是一种鸭子类型的语言,这种防御性编码水平积极地阻碍了这一点。Python 类型系统背后的想法是,只要对象以它需要的方式传入函数,事情就应该工作。通过执行显式类型检查,您将强制调用方使用特定类型,这与语言的本质背道而驰。虽然有时这样的事情是必要的(不包括字符串被视为序列),但这种情况很少见,几乎总是最好作为黑名单。
1赞 RemcoGerlich 7/16/2015
如果你真的想检查这个值是否准确,而不是另一种类型的虚假的东西,那么肯定是需要的,而不是用isinstance来捣乱。[]if a == []:
2赞 dubiousjim 7/16/2015
不过,有一些自动胁迫。在我的头顶上,我无法识别任何. 例如,返回 .但例如返回 .因此,至少值得考虑一下,在做这些事情时,某些不受欢迎的类型是否会被胁迫(反之亦然)。==[][] == ()Falsefrozenset()==set()True[]a == []
1赞 Tim 7/10/2019
@Boris 类型提示可帮助静态类型检查器(如 mypy)检查类型正确性,但不执行运行时类型检查。
122赞 abarnert 12/3/2014 #9

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

Python 代码和 Python 社区具有非常强的习语。遵循这些习语可以使任何有 Python 经验的人更容易阅读您的代码。当你违反这些习语时,这是一个强烈的信号。

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

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

评论

2赞 joel 6/17/2020
“当你违反这些习语时,这是一个强烈的信号。这可能是一个强烈的信号,表明你只是在使用由刚接触 python 的人编写的代码,这是很多人
107赞 MrWonderful 10/7/2015 #10

为什么要检查?

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

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

a = []

for item in a:
    # <Do something with item>

# <The rest of code>

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

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

a = []

if not a:
    # <React to empty list>

# <The rest of code>

就足够了。

评论

6赞 Amarth Gûl 2/2/2018
问题是,检查列表是否为空非常重要,至少对我来说是这样。你有没有考虑过里面是否有一些脚本可能会使用循环的结果?或者直接使用中的一些值?事实上,如果脚本被设计为使用严格控制的输入运行,则检查可能有点没有必要。但在大多数情况下,输入会有所不同,检查通常更好。<rest of code>fora
2赞 MrWonderful 2/18/2018
恭敬地,没有。我考虑的是,一个对 Python 不够了解的人知道“if <list>:” 是正确的答案,问如何检查空列表。然后我注意到很多答案提供了不同的意见,但似乎没有一个能解决最初的需求。这就是我试图用我的答案做的——让他们在继续之前检查一下需求。我相信我在回答中明确地提出了同样多的建议。
1赞 MrWonderful 5/23/2018
@AmarthGûl - 如何结果从 for 循环获取到要处理的脚本<其余代码>?也许在列表中?或者也许是字典?如果是这样,则适用相同的逻辑。我不明白变量输入如何在任何合理设计的代码中产生任何影响,其中处理空列表将是一个坏主意。
12赞 MrWonderful 6/27/2019
@DJK - 不,我想你仍然想念它。大概你想用一个列表做点什么,如果你有的话。如果它是空的,你会怎么做?早点回来?如果它不是空的怎么办?处理它?关键是,你可能不需要检查一个空列表,只需遍历它并执行你要对元素执行的任何操作。如果没有元素,你就会失败。如果有元素,您可以根据需要处理它们。关键是不要使用示例进行空检查,而是根本不检查,只需处理列表即可。
3赞 PieterNuyts 8/10/2022
很好的答案,但是一个语法错误。它应该是 .!anot a
38赞 Sнаđошƒаӽ 1/2/2016 #11

摘自有关真值测试的文档

除此处列出的值外,其他所有值都将被考虑在内True

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

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

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

评论

0赞 Sнаđошƒаӽ 9/1/2018
@DJ_Stuffy_K断言什么在单元测试中,一个空列表?只需使用 .如果你还想断言对象是 ,你可以使用 assertIsInstance()。assert(not myList)list
18赞 Tagar 4/14/2016 #12
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

虽然它一文不值,但那是虚假的。因此,如果您不想将 -ness 的测试分开,则不必这样做。NoneNone

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

评论

1赞 HighExodus 11/24/2020
恕我直言,这是最好的答案。它解决了测试时与和(空列表)相关的细微差别。None[]
25赞 Sunil Lulla 9/13/2016 #13

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

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

我喜欢这种方式,因为检查清单是空的还是空的。

非常方便和有用。

评论

8赞 Galen Long 3/11/2017
对于那些不知道的人(像我一样),将 Python 变量转换为布尔值,这样您就可以存储值的真实性或虚假性,而无需使用 if 语句。我认为它的可读性不如简单地使用像公认的答案这样的条件,但我相信还有其他好的用例。bool()
0赞 qneill 12/19/2017
这在表达式中可用,并且更简洁。
1赞 Lars P 9/30/2020
不利的一面发生在 .这通常是可以接受的,只是要注意。a is None
37赞 Taufiq Rahman 11/28/2016 #14

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

a = [] #the list

1)非常简单的pythonic方式:

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

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

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")
11赞 AndreyS Scherbakov 3/29/2017 #15

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

import collections
def 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

评论

2赞 pppery 7/12/2017
过于宽泛;这只是询问列表是否为空,而不是某些东西是否为空的可迭代对象。
1赞 Davis Herring 9/20/2017
如果我不满意,那是因为如果不是某种容器,我想要一个例外。(作为可迭代对象还允许迭代器,而迭代器无法有效地测试空性。if a:a
365赞 Russia Must Remove Putin 8/20/2017 #16

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

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

a = []

如何检查 a 是否为空?

简短的回答:

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

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

PEP 8

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

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

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 中甚至在语义上是正确的。

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

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

默认情况下,除非对象的类定义,否则该对象被视为 true 返回的方法或方法 当与对象一起调用时,返回零。以下是大多数被视为 false 的内置对象:__bool__()False__len__()

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

以及数据模型文档:

object.__bool__(self)

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

object.__len__(self)

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

所以而不是这个:

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

我们看到,与使用内置函数相比,使用内置函数检查长度检查空列表的性能不如使用所记录的语言的内置语法。len0

为什么?

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

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

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

>>> 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

这是添加字段的扩展。这仅用于具有某种长度概念的对象。此类型通常不会出现在 Python/C API 中。它对应于宏扩展定义的字段。PyObjectob_sizePyObject_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

对评论的回应:

我要指出的是,对于非空情况也是如此,尽管它非常丑陋,例如 90.6 ns ± 8.3 ns、55.6 ns ± 3.09、38.5 ns ± 0.372。但是,尽管速度提高了三倍,但任何人都无法享受。这看起来很荒谬。但是速度胜出,我想问题出
在使用 timeit 进行测试,因为 just 就足够了,但令人惊讶的是产生了 101 ns ± 2.64 ns。有趣的是,如果没有这种惩罚,就没有办法强迫布尔。 是无用的,因为不会发生转换。
l=[]%timeit len(l) != 0%timeit l != []%timeit not not lnot not lif l:%timeit bool(l)%timeit l

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)

我们可以看到,这里每增加一个,就会有一些线性成本。我们希望看到成本,ceteris paribus,也就是说,其他条件都相同 - 所有其他成本都尽可能最小化:not

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)

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

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

评论

1赞 Gregory Morse 11/28/2019
我要指出的是,对于非空情况也是如此,尽管它非常丑陋,例如 90.6 ns ± 8.3 ns、55.6 ns ± 3.09、38.5 ns ± 0.372。但是,尽管速度提高了三倍,但任何人都无法享受。这看起来很荒谬。但速度胜出l=[]%timeit len(l) != 0%timeit l != []%timeit not not lnot not l
1赞 Gregory Morse 11/28/2019
我想问题出在使用 timeit 进行测试,因为 just 就足够了,但令人惊讶的是产生了 101 ns ± 2.64 ns。有趣的是,如果没有这种惩罚,就没有办法强迫布尔。 是无用的,因为不会发生转换。if l:%timeit bool(l)%timeit l
10赞 ClementWalter 11/17/2020
到目前为止最好的答案,谢谢!用magicmethods指出python的真实逻辑,“Python是用C语言编写的;它在 C 级别使用其逻辑。你用 Python 编写的任何内容都会变慢。而且它可能会慢几个数量级“是关键。否则,一个人就会陷入“偏好”,永远不会得到一个正确的结论。
2赞 Ice Bear 12/19/2020
伟大!这是最好的答案!对于从 2020 年(现在是 12 月,所以差不多是 2021 年)和未来阅读的任何人。做是“Pythonic”方式和最好的方式,因为这个家伙解释得很好,并且还提供了一些为每个建议答案计算的时间性能的示例代码,所以很明显这个()要快得多,而且必须练习!if lif len(a) == 0if [] == []if aif a
0赞 12431234123412341234123 9/21/2021
你仍然没有解释为什么你应该使用.在 99% 中,我不在乎这种微小的性能差异,更喜欢可读性。 更易于阅读,更明确,并且在使用不是某种列表的内容时会出现错误,这就是为什么更有意义。顺便说一句,我只得到了大约 15% 的性能差异。if lsif len(ls)if len(ls)if len(ls)not len([])not []
8赞 Vineet Jain 8/27/2017 #17

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

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

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

评论

3赞 Davis Herring 9/20/2017
顾名思义,它返回了一些东西。但如果是这样,那东西就只是 ,你应该用它来代替(当你需要的时候)。is_emptybool(any_structure)bool
4赞 Davis Herring 9/20/2017
为什么我们想要一个变体(也)将消息打印到标准输出?bool
0赞 Vineet Jain 9/20/2017
@DavisHerring我们总是有两个选择,第一个是使用函数打印,另一个是使用返回变量。选择权在您手中。我都写了,所以你可以在它们之间进行选择。bool
15赞 Rahul 3/5/2018 #18

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

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 False
    else:
        return all(bool(x) for x in l)

现在,您可以使用:

if empty_list(lst):
    # do your stuff.

评论

2赞 gberger 3/6/2018
all(bool(x) for x in l) 对于空列表为 True
6赞 figs_and_nuts 5/16/2018 #19

空列表的真值为 ,而对于非空列表,它是 。FalseTrue

8赞 Ashiq Imran 10/12/2018 #20

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

if len(a) == 0:
    print("a is empty")
15赞 HackerBoss 10/12/2018 #21

已经给出了很多答案,其中很多都相当不错。我只是想补充一下,检查

not a

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

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

评论

0赞 Sven-Eric Krüger 1/10/2019
如果不是列表并且没有实现方法,则可能会引发异常。我会推荐:aa__len__if isinstance(obj, list): if len(obj) == 0: print '...'
9赞 ElmoVanKielmo 2/26/2019
@SvenKrüger没有。运算符在 Python 中是懒惰的。如果 condition before 为 False,则不会执行 after。andandand
14赞 Andrey Topoleov 11/3/2018 #22
print('not empty' if a else 'empty')

更实用一点:

a.pop() if a else None

和最短的版本:

if a: a.pop() 
7赞 Trect 11/6/2018 #23

从 python3 开始,你可以使用

a == []

检查列表是否为空

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

我不确定为什么有这么多复杂的答案。 它非常清晰和直接

评论

2赞 GD- Ganesh Deshmukh 12/30/2018
请提供更多关于它是如何工作的解释,而不写“如果”?
4赞 MrWonderful 4/29/2019
这不是pythonic,也不是一个完整的例子。此外,每次遇到空列表时,它都会实例化一个空列表。别这样。
2赞 Trect 4/6/2020
@MrWonderful它不会每次都实例化一个空列表。它只是验证现有列表是否为空。a
2赞 Trect 4/6/2020
@MrWonderful 我不明白是什么造就了它pythonic
1赞 Trect 4/6/2020
@ganeshdeshmukh如果使用它,如果 a 为空,它将在 python 终端上打印 true。否则将打印 False。您也可以在 if 条件中使用它,也可以作为a==[]if(a==[])
19赞 Andy Jazz 12/26/2018 #24

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

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".

第二种方式是更 Python 的方式。此方法是一种隐式检查方法,比前一种方法更可取。

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"

评论

1赞 David Frick 8/17/2020
还为显示如何检查它是否为空而点赞!这有助于涵盖相反但同样重要的用例
2赞 Alexis Drakopoulos 2/2/2021
请注意,第二个可能不适用于其他常见的数组类型对象,例如 numpy 数组。
11赞 l. zhang 1/7/2019 #25

我们可以使用一个简单的 if else

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

评论

5赞 MrWonderful 4/29/2019
-1 - 为避免混淆,不要对变量名使用保留字,否则下次尝试调用时可能会遇到令人惊讶的行为,例如“list()”...类似“TypeError: 'list' object is not callable”之类的东西。
31赞 Vikrant 2/10/2019 #26

方法 1(首选):

if not a:
   print ("Empty")

方法2:

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

方法3:

if a == []:
  print ("Empty")
6赞 Vedran Šego 4/24/2019 #27

把我带到这里来是一个特殊的用例:我实际上想要一个函数来告诉我列表是否为空。我想避免在这里编写自己的函数或使用 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)))

当然,不要使用 in (i.e., ),因为它是隐含的。但是,对于明确需要“不为空”作为函数的情况,是最佳选择。boolifif bool(L):bool