Я успешно пользовался библиотекой.NET Проекта Инди, чтобы сделать FTP. И... тьфу, похож на размещенную сборку.NET, больше не доступно.
Я объединил использование isinstance ()
от Ants Aasma и all (map ())
от ] Stephan202 , чтобы получить следующее решение. all ([])
возвращает True
, и функция полагается на это поведение. Я думаю, что в нем есть лучшее из обоих, и он лучше, поскольку он не полагается на исключение TypeError
.
def isListEmpty(inList):
if isinstance(inList, list): # Is a list
return all( map(isListEmpty, inList) )
return False # Not a list
If you do not need to iterate through the lists, simpler is better, so something like this will work:
def empty_tree(input_list):
"""Recursively iterate through values in nested lists."""
for item in input_list:
if not isinstance(item, list) or not empty_tree(item):
return False
return True
However, it would be good to separate the recursive iteration that you will most probably reuse elsewhere and checking that it returns no elements. This way if the mechanism of iteration changes you need to implement the change in one place. For instance when you need to support arbitrary nested iterables, or nested dicts.
def flatten(input_list):
"""Recursively iterate through values in nested lists."""
for item in input_list:
if isinstance(item, list): # Use what ever nesting condition you need here
for child_item in flatten(item):
yield child_item
else:
yield item
def has_items(seq):
"""Checks if an iterator has any items."""
return any(1 for _ in seq)
if not has_items(flatten(my_list)):
pass
Простой код, работает для любого итерируемого объекта, а не только для списков:
>>> def empty(seq):
... try:
... return all(map(empty, seq))
... except TypeError:
... return False
...
>>> empty([])
True
>>> empty([4])
False
>>> empty([[]])
True
>>> empty([[], []])
True
>>> empty([[], [8]])
False
>>> empty([[], (False for _ in range(0))])
True
>>> empty([[], (False for _ in range(1))])
False
>>> empty([[], (True for _ in range(1))])
False
Этот код предполагает, что все, что может быть повторено, будет содержать другие элементы и не должно рассматриваться как лист в дереве". Если попытка перебрать объект не удалась, то это не последовательность, и, следовательно, определенно не пустая последовательность (таким образом, возвращается False
). Наконец, этот код использует тот факт, что all
возвращает True
, если его аргумент - пустая последовательность.
Я не думаю, что есть очевидный способ сделать это в Python. Лучше всего использовать рекурсивную функцию вроде этой:
def empty(li):
if li == []:
return True
else:
return all((isinstance(sli, list) and empty(sli)) for sli in li)
Обратите внимание, что all
поставляется только с Python> = 2.5, и что он не будет обрабатывать бесконечно рекурсивные списки (например, a = []; a.append (a)
).
Достаточно простой рекурсивной проверки, и возврат будет как можно раньше, мы предполагаем, что ввод не является списком или содержит не списки, это не пусто
def isEmpty(alist):
try:
for a in alist:
if not isEmpty(a):
return False
except:
# we will reach here if alist is not a iterator/list
return False
return True
alist = []
blist = [alist] # [[]]
clist = [alist, alist, alist] # [[], [], []]
dlist = [blist] # [[[]]]
elist = [1, isEmpty, dlist]
if isEmpty(alist):
print "alist is empty"
if isEmpty(dlist):
print "dlist is empty"
if not isEmpty(elist):
print "elist is not empty"
Вы можете улучшить его для проверки наличия рекурсивного списка или отсутствия объектов списка, или может быть пустым dicts и т. д.