题
例如,如果通过以下内容:
a = []
我如何检查是否 a
是空的?
解决方案
if not a:
print("List is empty")
使用空的隐式布尔性 list
非常Pythonic。
其他提示
执行此操作的 pythonic 方法来自 PEP 8 风格指南 (在哪里 是的 意思是“推荐”并且 不 意思是“不推荐”):
对于序列(字符串、列表、元组),请使用空序列为 false 的事实。
是的: 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 测试空数组” 。
其他方法不适用于 NumPy 数组
您需要小心使用 NumPy 数组,因为其他方法也适用于 list
s 或其他标准容器对于 NumPy 数组失败。我在下面解释原因,但简而言之, 首选方法 是使用 size
.
“pythonic”方式不起作用:第1部分
“pythonic”方式对于 NumPy 数组失败,因为 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 常见问题解答, ,在您知道有 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
检查我在此页面上看到的所有情况的工作。
检查列表是否为空的最佳方法
例如,如果通过以下内容:
a = []
如何检查 a 是否为空?
简短回答:
将列表放在布尔上下文中(例如,使用 if
或者 while
陈述)。它将测试 False
如果它是空的,并且 True
否则。例如:
if not a: # do this!
print('a is an empty list')
向当局上诉
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 中甚至在语义上也是正确的。
但我们认为它不是 Pythonic,因为 Python 通过布尔强制直接在列表对象的接口中支持这些语义。
来自 文档 (并特别注意包含空列表, []
):
默认情况下,一个对象被认为是正确的,除非其类别定义
__bool__()
返回的方法False
或一个__len__()
与对象调用时返回零的方法。以下是大多数被视为 false 的内置对象:
- 常量定义为 false:
None
和False
.- 任何数字类型的零:
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
- 空序列和集合:
''
,()
,[]
,{}
,set()
,range(0)
以及数据模型文档:
调用实现真值测试和内置操作
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')
做 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
被阴影覆盖。
然后它必须调用函数,load 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 源代码和文档的证据
这是一个扩展
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
我很喜欢研究这个,并且花了很多时间来整理我的答案。如果您认为我遗漏了某些内容,请在评论中告诉我。
在真值测试中,空列表本身被视为错误(请参阅 python 文档):
a = []
if a:
print "not empty"
@达伦·托马斯
编辑:反对测试空列表为false的另一点:多态性呢?您不应该依赖列表为列表。它应该像鸭子一样颤抖 - 当它没有元素时,您将如何使鸭子填充'false''?
你的 duckCollection 应该实现 __nonzero__
或者 __len__
所以如果:将毫无问题地工作。
帕特里克(接受)的回答 是对的: 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:
是在误导读者。你正在发出同样重要的信号,而实际上它并不重要。(您也可能会降低代码的灵活性,或者变慢,或者其他什么,但这都不那么重要。)如果您 习惯性地 像这样误导读者,那么当你 做 需要做出区分,它会被忽视,因为你一直在你的代码中“喊狼来了”。
为什么要检查?
似乎没有人回答过你的问题 需要 首先测试该列表。因为您没有提供额外的上下文,所以我可以想象您可能不需要首先进行此检查,但不熟悉 Python 中的列表处理。
我认为 最Pythonic 方法是根本不检查,而只是处理列表。这样,无论是空的还是满的,它都会做正确的事情。
a = []
for item in a:
<do something with item>
<rest of code>
这有利于处理任何内容 A, ,同时不需要对空性进行特定检查。如果 A 为空,依赖块将不会执行,解释器将跳到下一行。
如果您确实需要检查数组是否为空,那么其他答案就足够了。
len()
是一个 O(1) 操作 适用于 Python 列表、字符串、字典和集合。Python 在内部跟踪这些容器中的元素数量。
JavaScript 有类似的真/假概念.
我曾写道:
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
或者布尔类型转换可能不会完全符合您的预期。
从 文档 关于真值测试:
除此处列出的值之外的所有值均被考虑 True
None
False
- 任何数字类型的零,例如,
0
,0.0
,0j
. - 任何空序列,例如
''
,()
,[]
. - 任何空映射,例如
{}
. - 用户定义类的实例,如果该类定义了
__bool__()
或者__len__()
方法,当该方法返回整数零或布尔值时False
.
可以看到,列表为空 []
是 虚假的, ,所以对布尔值执行的操作听起来最有效:
if not a:
print('"a" is empty!')
您可以通过以下几种方法检查列表是否为空:
a = [] #the list
1) 非常简单的Python方式:
if not a:
print("a is empty")
在Python中, 空容器 例如列表、元组、集合、字典、变量等被视为 False
. 。人们可以简单地将列表视为谓词(返回一个布尔值)。还有一个 True
value 将表明它非空。
2) 一个非常明确的方式:使用 len()
找到长度并检查它是否等于 0
:
if len(a) == 0:
print("a is empty")
3) 或者将其与匿名空列表进行比较:
if a == []:
print("a is empty")
4) 还有一个 愚蠢的 方法是使用 exception
和 iter()
:
try:
next(iter(a))
# list has elements
except StopIteration:
print("Error: a is empty")
我更喜欢以下内容:
if a == []:
print "The list is empty."
方法一(首选):
if not a :
print ("Empty")
方法二:
if len(a) == 0 :
print( "Empty" )
方法三:
if a == [] :
print ("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 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
已经给出了很多答案,其中很多都很好。我只是想补充一下支票
not a
也将通过 None
和其他类型的空结构。如果您确实想检查空列表,可以这样做:
if isinstance(a, list) and len(a)==0:
print("Received an empty list")
受到 @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
您甚至可以尝试像这样使用 bool()
a = [1,2,3];
print bool(a); # it will return True
a = [];
print bool(a); # it will return False
我喜欢这种检查列表是否为空的方式。
非常方便和有用。
简单的方法是检查长度是否为零。
if len(a) == 0:
print("a is empty")
print('not empty' if a else 'empty')
更实用一点:
a.pop() if a else None
从python3开始你可以使用
a == []
检查列表是否为空
编辑 :这也适用于 python2.7..
我不知道为什么有这么多复杂的答案。非常清晰明了
我们可以使用一个简单的 if else:
list=[]
if len(list)==0:
print ("list is empty")
else:
print ("list is not empty")
只需使用 is_empty() 或制作如下函数:-
def is_empty(any_structure):
if any_structure:
print('Structure is not empty.')
return True
else:
print('Structure is empty.')
return False
它可用于任何数据结构,如列表、元组、字典等。通过这些,您可以使用多次调用它 is_empty(any_structure)
.
要检查列表是否为空,可以使用以下两种方法。但请记住,我们应该避免显式检查序列或列表的方式(它是一个
less pythonic
方式):
def Enquiry(list1):
if len(list1) == 0:
return 0
else:
return 1
# ––––––––––––––––––––––––––––––––
list1 = []
if Enquiry(list1):
print ("The list isn't empty")
else:
print("The list is Empty")
# Result: "The list is Empty".
第二种方法是
more pythonic
一。这种方法是一种隐式检查方式,比前一种方法更好。
def Enquiry(list1):
if not list1:
return 1
else:
return 0
# ––––––––––––––––––––––––––––––––
list1 = []
if Enquiry(list1):
print ("The list is Empty")
else:
print ("The list isn't empty")
# Result: "The list is Empty"
希望这可以帮助。
检查是否: len(list) == 0
返回: True
如果你想检查列表是否为空;
l = []
if l:
# do your stuff.
如果你想检查天气,列表中的所有值都是空的。
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.
空列表的真值是 False
而对于非空列表来说是 True
.
让我来到这里的是一个特殊的用例:我其实想要一个 功能 告诉我列表是否为空。我想避免在这里编写自己的函数或使用 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)))
当然,做 不是 使用 bool
在 if
(IE。, if bool(L):
)因为这是隐含的。但是,对于明确需要“不为空”作为函数的情况, bool
是最好的选择。
一种愚蠢的使用方式 pop
和 try
except
条款(不推荐):
a = []
try:
a.pop()
print('list isn\'t empty')
except:
print('list is empty')
输出:
list is empty
非官方的方法:
a = []
try:
print(a[-1])
except IndexError:
print("List is empty")