检查列表是否为空的最佳方法
例如,如果通过如下:
a = []
如何检查a
是否为空?
if not a: print("List is empty")
使用空列表的隐式布尔型是相当pythonic。
Pythonic的做法是从PEP 8风格指南 :
对于序列(string,列表,元组),使用空序列为假的事实。
Yes: if not seq: if seq: No: if len(seq): if not len(seq):
我明确地喜欢它:
if len(li) == 0: print('the list is empty')
这样100%清楚li
是一个序列(列表),我们想testing它的大小。 我的问题, if not li: ...
它给出了错误的印象, li
是一个布尔variables。
其他人似乎将这个问题推广到了列表之外,所以我想为一个不同types的序列添加一个警告,很多人可能会使用它,尤其是因为这是第一个针对“python test empty array” 。
其他方法不适用于numpy数组
您需要小心numpy数组,因为对于numpy数组而言,对于list
s或其他标准容器工作正常的其他方法都会失败。 我解释下面的原因,但总之, 首选的方法是使用size
。
“pythonic”方式不起作用:第1部分
“pythonic”方式因为numpy数组失败,因为numpy试图将数组转换为一个bool
s数组, if x
试图为某种types的聚合真值计算所有这些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()
“pythonic”方式不起作用:第2部分
但至less上面的情况告诉你,它失败了。 如果碰巧有一个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,即使该数组有零元素。
nypythonic的方式
正如在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给出的答案结合起来,以确保每种types都使用正确的testing。 不是非常“pythonic”,但事实certificate,numpy至less在这个意义上故意打破pythonicity。
如果您需要做的不仅仅是检查input是否为空,而且您正在使用索引或math运算等其他numpyfunction,那么强制input可能更为有效(当然更常见)。 有几个很好的function,这样做很快 – 最重要的是numpy.asarray
。 这需要你的input,如果它已经是一个数组,也不做任何事情,或者如果它是一个列表,元组等,将你的input包装到一个数组中,并且可选地将其转换为你所select的dtype
。 所以,只要可能,它就会很快,并且确保您只是假设input是一个numpy数组。 我们通常甚至只是使用相同的名称,因为转换到数组不会超出当前范围 :
x = numpy.asarray(x, dtype=numpy.double)
这将使x.size
检查在我看到的所有情况下工作。
一个空列表本身在真正的值testing中被认为是错误的(请参阅python文档 ):
a = [] if a: print "not empty"
@Daren Thomas
编辑:反对testing空列表为False的另一点:多态性呢? 你不应该依赖列表作为列表。 它应该像鸭子一样嘎嘎 – 你怎样才能让你的鸭子集合在没有任何元素的时候呱呱叫“假”呢?
你的duckCollection应该实现__nonzero__
或__len__
这样if a:就可以正常工作。
帕特里克(接受)的答案是正确的: if not a:
是正确的做法。 哈雷Holcombe的答案是正确的,这是在PEP 8风格指南。 但是没有答案解释为什么遵循这个习惯用法是一个好主意 – 即使你个人觉得它不够明确,或者对Ruby用户或其他方面感到困惑。
Python代码和Python社区都有很强的习惯用法。 遵循这些习惯用法,您可以更轻松地阅读任何经验丰富的Python代码。 而当你违反这些成语时,这是一个强烈的信号。
确实, if not a:
不区分空列表与None
,数字0或空元组,或者空的用户创build的集合types,或者空的用户创build的非完全集合types或单元素NumPy数组充当虚伪价值的标量,等等。有时候要明确这一点很重要。 在这种情况下,你知道你想要明确什么,所以你可以testing。 例如, if not a and a is not None:
意思是“除了None之外什么都是假的”,而if len(a) != 0:
意思是“只有空序列 – 除了序列之外的任何东西都是错误”等等。 除了testing你想要testing的东西,这也告诉读者,这个testing是重要的。
但是当你没有什么需要明确的地方时, if not a:
误导读者。 如果不是这样的话,你的信号就显得很重要。 (你也可能会使代码变得更不灵活,或者更慢,或者其他任何东西,但这一切都不那么重要。)如果你习惯性地误导读者这样做,那么当你需要区分时,它会被忽视,因为你已经在你的代码中“哭泣”了。
我已经看到下面的首选,因为它也会列入空列表:
if not a: print "The list is empty or null"
len()
是 Python列表,string,字典和集合的O(1)操作 。 Python在内部跟踪这些容器中元素的数量。
JavaScript 有一个相似的真理/错误的概念 。
似乎没有人提出质疑你需要首先testing列表。 因为您没有提供额外的上下文,所以我可以想象,您可能不需要首先执行此检查,但不熟悉Python中的列表处理。
我会认为, 最pythonic的方式是不检查,而是只是处理清单。 这样,无论是空的还是满的,它都会做正确的事情。
a = [] for item in a: <do something with item> <rest of code>
这有利于处理a的任何内容,而不需要特定的空白检查。 如果a为空,则依赖块将不执行,并且解释器将落入下一行。
如果你真的需要检查arrays的空虚,其他答案就足够了。
检查列表是否为空的最佳方法
例如,如果通过如下:
a = []
如何检查一下是否为空?
简答:
将列表放置在布尔上下文中(例如,使用if
或while
语句)。 如果为空则会testingFalse
,否则为True
。 例如:
if not a: # do this! print('a is an empty list')
呼吁权威
PEP 8是Python标准库中Python代码的官方Python风格指南,声明:
对于序列(string,列表,元组),使用空序列为假的事实。
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通过布尔强制直接在列表对象的接口中支持这些语义。
从文档 (特别注意包含空列表, []
):
默认情况下,一个对象被认为是真的,除非它的类定义了一个返回
False
的__len__()
方法或者一个返回零的__len__()
方法。 以下是大多数被认为是错误的内置对象:
- 定义为false的常量:
None
和False
。- 任何数字types的零:
0j
,Decimal(0)
,Fraction(0, 1)
- 空序列和集合:
''
,()
,[]
,{}
,set()
,range(0)
数据模型文档:
object.__bool__(self)
被调用来实现真值testing和内置操作
bool()
; 应该返回False
或True
。 当这个方法没有被定义的时候,__len__()
被调用,如果它被定义的话,那么如果这个对象的结果是非零的,它就被认为是真的。 如果一个类既没有定义__len__()
也没有定义__bool__()
,它的所有实例都被认为是真的。
和
object.__len__(self)
调用来实现内置函数
len()
。 应该返回对象的长度,一个> = 0的整数。另外,一个没有定义__bool__()
方法的对象,其__len__()
方法返回0在布尔上下文中被认为是错误的。
所以,而不是这个:
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通常会在性能上得到回报:
它还清吗? (请注意,执行等效操作的时间会更less:)
>>> import timeit >>> min(timeit.repeat(lambda: len([]) == 0, repeat=10)) - min(timeit.repeat(lambda: [], repeat=10)) 0.07626811624504626 >>> min(timeit.repeat(lambda: [] == [], repeat=10)) - min(timeit.repeat(lambda: [], repeat=10)) 0.032089774729683995 >>> min(timeit.repeat(lambda: not [], repeat=10)) - min(timeit.repeat(lambda: [], repeat=10)) 0.008945178240537643
我们看到, 使用内置函数len
比较0
来检查长度, 或者检查空列表的性能比使用所logging的语言的内build语法低得多。
为什么?
对于len(a) == 0
检查:
首先,Python必须检查全局variables,看是否有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
对于[] == []
它必须build立一个不必要的列表,然后在Python的虚拟机中进行比较操作(而不是C)
>>> dis.dis(lambda: [] == []) 1 0 BUILD_LIST 0 2 BUILD_LIST 0 4 COMPARE_OP 2 (==) 6 RETURN_VALUE
由于列表的长度被caching在对象实例头中,所以“Pythonic”方法更简单快速的检查:
>>> dis.dis(lambda: not []) 1 0 BUILD_LIST 0 2 UNARY_NOT 4 RETURN_VALUE
来自C源和文档的证据
PyVarObject
这是
PyObject
的扩展,添加了ob_size
字段。 这仅用于具有某种长度概念的对象。 这种types不会经常出现在Python / C API中。 它对应于由PyObject_VAR_HEAD
macros扩展定义的字段。
从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
我很喜欢研究这个,我花了很多时间来策划我的答案。 如果你觉得我要留下一些东西,请在评论中告诉我。
Python对于空虚的处理非常统一。 鉴于以下情况:
a = [] . . . if a: print("List is not empty.") else: print("List is empty.")
您只需使用“if”语句检查列表a是否为空。 从我读过的和被教过的,这是“Pythonic”的方法,看看列表或元组是空的。
我写了:
if isinstance(a, (list, some, other, types, i, accept)) and not a: do_stuff
其中投了-1。 我不确定这是因为读者反对这个策略,或者认为答案没有提供帮助。 我会假装是后者,因为 – 无论什么都算作“pythonic” – 这是正确的策略。 除非你已经排除了,或者准备处理a
例如是False
情况,否则你需要一个更严格的testing,而不仅仅是if not a:
。 你可以使用这样的东西:
if isinstance(a, numpy.ndarray) and not a.size: do_stuff elif isinstance(a, collections.Sized) and not a: do_stuff
第一个testing是回应@迈克的答案,上面。 第三行也可以replace为:
elif isinstance(a, (list, tuple)) and not a:
如果您只想接受特定types(及其子types)的实例,或者:
elif isinstance(a, (list, tuple)) and not len(a):
你可以在没有显式types检查的情况下离开,但是只有当周围的上下文已经向你保证a
是你准备处理的types的值,或者如果你确定你没有准备处理的types是如果你准备处理的话,会引发错误(例如,如果你调用了一个未定义的值的话,就是一个TypeError
)。 一般来说,“pythonic”惯例似乎走到最后。 像鸭子一样挤压它,如果它不知道如何嘎嘎,让它引起一个DuckError。 但是,你仍然需要考虑你正在做什么types的假设,以及你是否准备好正确处理的情况,是否会在正确的地方出错。 Numpy数组就是一个很好的例子,只是盲目地依赖len
或者booleantypes转换可能并不能满足你所期望的。
从真值testing的文件 :
除了这里列出的所有值都被认为是True
-
None
-
False
- 任何数字types的零,例如
0j
。 - 任何空序列,例如
''
,()
,[]
。 - 任何空的映射,例如
{}
。 - 如果该类定义了
__bool__()
或__len__()
方法,则该方法返回整数零或布尔值False
时,用户定义的类的实例。
可以看出,空列表[]
是虚假的 ,所以做一个布尔值将是最有效的:
if not a: print('"a" is empty!')
以下是一些可以检查列表是否为空的方法:
a = [] #the list
1)非常简单的pythonic方式:
if not a: print("a is empty")
在Python中, 空的容器如列表,元组,集合,字典,variables等被视为False
。 人们可以简单地将列表视为一个谓词( 返回一个布尔值 )。 而一个True
值将表明它是非空的。
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."
可读,您不必担心调用像len()
函数遍历variables。 尽pipe我不完全确定BigO这种类似的东西是什么意思……但是Python的速度如此之快,我怀疑除非是巨大的,否则这一点很重要。
一些方法我使用:
if not a: print "list is empty" if not bool(a): print "list is empty" if len(a) == 0: print "list is empty"
当然也有
print a or "List 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
和“空”的testing,有时候是好的,因为这是两种不同的状态。 上面的代码产生以下输出:
list is None list is empty list has 3 elements
虽然没有什么是虚伪的。 所以,如果你不想单独testingNoneness,你不必这样做。
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
你甚至可以尝试像这样使用bool()
a = [1,2,3]; print bool(a); # it will return True a = []; print bool(a); # it will return False
我喜欢这种检查清单是否为空的方式。
非常方便和有用的。
受到@ dubiousjim解决scheme的启发,我build议使用额外的一般检查是否是可迭代的
import collections def is_empty(a): return not a and isinstance(a, collections.Iterable)
注意:一个string被认为是可迭代的。 – 如果要排除空string,则添加and not isinstance(a,(str,unicode))
testing:
>>> 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
只需使用is_empty()或者像下面这样创build函数:
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)
多次调用它。
你可以使用try和except,因为它比其他构造更便宜
a=[] try: x=a[0] except: print(' list is empty')