例如,如果传递以下内容:
a = []
我如何检查是否 a
是空的?
例如,如果传递以下内容:
a = []
我如何检查是否 a
是空的?
if not a:
print("List is empty")
使用空列表的隐式布尔值是非常pythonic。
if not a:
print("List is empty")
使用空列表的隐式布尔值是非常pythonic。
pythonic的方法来自于 PEP 8风格指南 (哪里 是 意思是“推荐”和 没有 意思是“不推荐”):
对于序列,(字符串,列表,元组),请使用空序列为假的事实。
是: if not seq: if seq: 没有: if len(seq): if not len(seq):
我明确地喜欢它:
if len(li) == 0:
print('the list is empty')
这样就可以100%清楚了 li
是一个序列(列表),我们想测试它的大小。我的问题 if not li: ...
是它给人的错觉 li
是一个布尔变量。
其他人似乎将这个问题概括为仅仅是列表,所以我想我会为很多人可能会使用的不同类型的序列添加一个警告,特别是因为这是“python test empty array”的第一个google点击。
你需要小心numpy数组,因为其他方法可以正常工作 list
s或其他标准容器因numpy数组而失败。我在下面解释原因,但简而言之, 首选方法 是用 size
。
“pythonic”方式因numpy数组失败,因为numpy尝试将数组转换为数组 bool
s,和 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()
但至少上面的情况告诉你它失败了。如果你碰巧有一个只有一个元素的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数组。快速完成这项工作有一些很好的功能 - 最重要的是 numpy.asarray
。这会接受你的输入,如果它已经是一个数组就什么都不做,或者如果它是一个列表,元组等,你的输入就会包装成一个数组,并且可以选择将它转换成你选择的 dtype
。所以只要它可以很快,它确保你只是假设输入是一个numpy数组。我们通常甚至只使用相同的名称,因为转换为数组不会使其回到当前的范围之外 范围:
x = numpy.asarray(x, dtype=numpy.double)
这将使 x.size
检查我在本页看到的所有情况下的工作。
在真值测试中,空列表本身被认为是假的(参见 python文档):
a = []
if a:
print "not empty"
@Daren Thomas
编辑:反对测试的另一点 空列表为False:怎么样 多态?你不应该依赖 列表是列表。它应该是 像鸭子一样嘎嘎叫 - 你怎么样 让你的duckCollection嘎嘎叫 没有元素的时候''''''
你的duckCollection应该实现 __nonzero__
要么 __len__
所以如果a:将没有问题。
检查列表是否为空的最佳方法
例如,如果传递以下内容:
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
。- 任何数字类型的零:
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
- 空序列和集合:
''
,()
,[]
,{}
,set()
,range(0)
和datamodel文档:
被称为实施真值测试和内置操作
bool()
;应该回来False
要么True
。如果未定义此方法,__len__()
如果已定义,则调用该对象,如果其结果为非零,则将该对象视为true。如果一个类都没有定义__len__()
也不__bool__()
,它的所有实例都被认为是真实的。
和
被称为实现内置功能
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')
它有回报吗? (注意,执行等效操作的时间越少越好:)
>>> 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
这是一个扩展
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
我很喜欢研究这个,我花了很多时间来策划我的答案。如果您认为我要留下一些东西,请在评论中告诉我。
帕特里克(接受)答案 是对的: 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:
误导了读者。当事实并非重要时,你就会发出重要的信号。 (你可能也会使代码变得不那么灵活,或者更慢,或者其他什么,但这些都不那么重要。)如果你 习惯性地 像这样误导读者,然后当你 做 需要做出区分,它会被忽视,因为你在你的代码中一直在“哭狼”。
我已经看到以下是首选:
if not a:
print("The list is empty or null")
似乎没有人质疑你的问题 需要 首先测试列表。因为您没有提供额外的上下文,我可以想象您可能不需要首先进行此检查,但不熟悉Python中的列表处理。
我会争辩说 大多数pythonic 方式是根本不检查,而是只处理列表。这样,无论是空的还是满的,它都会做正确的事情。
a = []
for item in a:
<do something with item>
<rest of code>
这有利于处理任何内容 一个,虽然不需要特别检查空虚。如果 一个 为空,依赖块将不会执行,解释器将进入下一行。
如果你确实需要检查数组是否空虚,那么其他答案就足够了。