Как проверить, если список пуст?

3234

Например, если передано следующее:

a = []

Как проверить, aпусто ли?

луч
источник

Ответы:

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

Использование неявного булева пустоты listдовольно питонно.

Патрик
источник
1130
Играя адвоката дьявола. Я не понимаю, почему эта идиома считается питонической. «Явное лучше, чем неявное», верно? Эта проверка, кажется, не очень ясно о том, что проверяет.
Джеймс МакМэхон
222
@JamesMcMahon - это компромисс между ясностью и гибкостью типов. как правило, «быть явным» означает не делать «волшебные» вещи. с другой стороны, «типизирование утки» означает работу с более общими интерфейсами, а не явную проверку типов. таким образом, что-то вроде if a == []принуждения определенного типа ( () == []есть False). здесь, по общему мнению, выигрывает типизация утки (фактически, говорят, что __nonzero__это интерфейс для проверки пустоты docs.python.org/reference/datamodel.html#object.__nonzero__ )
Эндрю Кук
38
Этот метод не работает с массивами numpy ... так что я думаю, что len (a) == 0 предпочтительнее как с точки зрения "утиной типизации", так и с точки зрения неявности.
Mr.WorshipMe
10
Канонический способ узнать, является ли массив в C пустым, - разыменовать первый элемент и посмотреть, является ли он нулевым, предполагая, что массив имеет нулевое окончание. В противном случае сравнение его длины с нулем совершенно неэффективно, если массив имеет значительный размер. Также, как правило, вы не будете выделять память для пустого массива (указатель остается нулевым), поэтому нет смысла пытаться получить его длину. Я не говорю, что len (a) == 0 не очень хороший способ сделать это, он просто не кричит мне «C», когда я это вижу.
Sleblanc
6
@BrennenSprimont, если он не заканчивается нулем, то вы уже знаете длину, хранится ли она в отдельной переменной, или ваш массив обернут в некоторый контейнер, который отслеживает длину. C ++, Java, C # имеют такие контейнеры и эффективно реализуют метод "length". С не имеет такой вещи , вы должны свернуть свои собственные. Статически распределенные массивы C - это всего лишь указатели на область памяти, в которой гарантированно достаточно места для хранения запрошенного вами объема данных. В C нет ничего, что позволило бы вам узнать, сколько вы уже заполнили это пространство.
Sleblanc
1160

Pythonic способ сделать это из руководства по стилю PEP 8 (где Да означает «рекомендуется», а Нет означает «не рекомендуется»):

Для последовательностей (строк, списков, кортежей) используйте тот факт, что пустые последовательности являются ложными.

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):
Харли Холкомб
источник
49
Второй способ кажется более подходящим, если вы хотите seqуказать, что ожидается, что это какой-то объект типа списка.
BallpointBen
5
@BallpointBen, который, как утверждают сторонники Pythonism, должен быть неявным в способе именования переменной, насколько это возможно
axolotl
9
@BallpointBen попробуйте использовать подсказку типа Python для обозначения переменной. Это было введено в 3.5.
Борис
8
numpy нарушил эту идиому ... seq = numpy.array ([1,2,3]), за которым следует, если нет, seq вызывает исключение "ValueError: Значение истинности массива с более чем одним элементом является неоднозначным. Используйте a.any () или a.all () "
Mr.WorshipMe
2
@jeronimo: я считаю, что это предупреждение для lxml.
Харли Холкомб
770

Я предпочитаю это явно:

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

Таким образом, на 100% ясно, что liэто последовательность (список), и мы хотим проверить ее размер. Моя проблема в if not li: ...том, что это создает ложное впечатление, что liэто логическая переменная.

Джабба
источник
91
Проверка того, равна ли длина списка нулю, а не просто проверка, является ли список ложным, уродлива и неуместна. Любой, кто знаком с Python, вообще не будет думать, что liэто глупость, и ему все равно. Если это важно, вы должны добавить комментарий, а не больше кода.
Карл Смит
21
Это кажется излишне точным тестом, который часто медленнее и всегда менее читабелен ИМХО. Вместо того, чтобы проверять размер чего-либо пустого, почему бы просто не проверить, пусто ли оно?
Джон Б
34
В любом случае, причина того, что это плохо (а нарушение идиом в языке с сильными идиомами, такими как Python, вообще плохо), заключается в том, что он сообщает читателю, что вы по какой-то причине специально проверяете длину (например, потому что вы хотите Noneили 0поднять исключение, а не мимоходом). Итак, когда вы делаете это без причины, что это вводит в заблуждении, и это также означает , что , когда ваш код делает потребность сделать различие, различие невидимо , потому что вы «кричал волк» во всем остальном источника.
Абарнерт
18
Я думаю, что это просто излишне удлиняет код. Иначе, почему бы не быть еще более "явным" с if bool(len(li) == 0) is True:?
Авгурар
11
@Jabba во многих случаях будет O (1) (в тех случаях, когда вы работаете со встроенными типами данных), но вы просто не можете на это полагаться. Возможно, вы работаете с пользовательским типом данных, у которого нет этого свойства. Вы можете также решить добавить этот пользовательский тип данных позже, после того, как вы уже написали этот код.
ralokt
325

Это первый хит Google для "пустого массива python test" и аналогичных запросов, плюс другие люди, кажется, обобщают вопрос за пределы списков, поэтому я решил добавить предостережение для последовательности другого типа, которую многие люди может использовать.

Другие методы не работают для массивов NumPy

Вы должны быть осторожны с массивами NumPy, потому что другие методы, которые отлично работают для lists или других стандартных контейнеров, не работают для массивов NumPy. Я объясню, почему ниже, но вкратце, предпочтительным методом является использование size.

«Питонический» способ не работает: часть 1

«Питонический» путь терпит неудачу с массивами NumPy, потому что NumPy пытается привести массив к массиву bools и if xпытается оценить все эти bools одновременно для некоторого совокупного значения истинности. Но это не имеет никакого смысла, поэтому вы получите 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()

«Питонический» способ не работает: часть 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, даже если массив содержит ноль элементов.

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

Если вы не уверены, что это может быть listмассив NumPy или что-то еще, вы можете объединить этот подход с ответом, который дает @dubiousjim, чтобы убедиться, что для каждого типа используется правильный тест. Не очень "pythonic", но оказывается, что NumPy преднамеренно нарушил pythonicity по крайней мере в этом смысле.

Если вам нужно сделать больше, чем просто проверить, является ли ввод пустым, и вы используете другие функции NumPy, такие как индексирование или математические операции, возможно, более эффективно (и, безусловно, более распространено), чтобы входные данные были массивом NumPy. Есть несколько хороших функций для быстрого выполнения этого - самое главное numpy.asarray. Он принимает ваш ввод, ничего не делает, если он уже является массивом, или упаковывает ваш ввод в массив, если это список, кортеж и т. Д., И при желании преобразует его в выбранный вами dtype. Так что это очень быстро, когда это возможно, и гарантирует, что вы просто предполагаете, что входные данные являются массивом NumPy. Обычно мы даже просто используем одно и то же имя, поскольку преобразование в массив не вернет его за пределы текущей области :

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

Это сделает x.sizeпроверку работоспособной во всех случаях, которые я вижу на этой странице.

Майк
источник
62
Стоит отметить, что это не недостаток в Python, а преднамеренный разрыв контракта numpy- numpyбиблиотека с очень конкретным случаем использования, и она имеет другое «естественное» определение того, что истинность в массиве для Стандарт Python для контейнеров. Имеет смысл оптимизировать для этого случая способом, который pathlibиспользуется /для объединения путей вместо +- это нестандартно, но имеет смысл в контексте.
Гарет Латти
9
Согласовано. Моя точка зрения заключается в том, что важно помнить, что numpy сделал выбор, чтобы сломать типизацию утки как для самых распространенных, так if xи для len(x)идиом, и иногда этот разрыв может быть очень трудно обнаружить и отладить.
Майк
22
Я не знаю, для меня, если метод с именем len (x) не возвращает длину массива из-за предположений, его имя плохо спроектировано.
Далтон
11
Этот вопрос не имеет никакого отношения к массивам numpy
pppery
19
@ppperry Да, оригинальный вопрос был не о массивах Numpy, но при работе с этими аргументами и, возможно, с типизированными утками, этот вопрос становится очень актуальным.
Петерхил
223

Лучший способ проверить, если список пуст

Например, если передано следующее:

a = []

Как проверить, пусто ли?

Короткий ответ:

Поместите список в логический контекст (например, с помощью оператора ifили while). Он проверит, Falseесли он пуст, и в Trueпротивном случае. Например:

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

ПКП 8

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 поддерживает эту семантику непосредственно в интерфейсе объекта списка посредством логического приведения.

Из документов (и обратите особое внимание на включение пустого списка []):

По умолчанию объект считается истинным, если только его класс не определяет либо __bool__()метод, который возвращает, Falseлибо __len__()метод, который возвращает ноль, когда вызывается с объектом. Вот большинство встроенных объектов, которые считаются ложными:

  • константы, определенные как ложные: Noneи False.
  • ноль любого числового типа: 0, 0.0, 0j, Decimal(0),Fraction(0, 1)
  • пустые последовательности и коллекции: '', (), [], {}, set(),range(0)

И документация по датамоделю:

object.__bool__(self)

Вызывается для выполнения проверки истинности значения и встроенной операции bool(); должен вернуться Falseили True. Когда этот метод не определен, __len__()вызывается, если он определен, и объект считается истинным, если его результат ненулевой. Если класс не определяет ни то, __len__() ни другое __bool__(), все его экземпляры считаются истинными.

а также

object.__len__(self)

Вызывается для реализации встроенной функции len(). Должен возвращать длину объекта, целое число> = 0. Кроме того, объект, который не определяет __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

Мы видим, что либо проверка длины с помощью встроенной функции 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

Данные из источника C и документации

PyVarObject

Это расширение, PyObjectкоторое добавляет ob_sizeполе. Это используется только для объектов, которые имеют некоторое представление о длине. Этот тип не часто появляется в Python / C API. Это соответствует полям, определенным расширением PyObject_VAR_HEADмакроса.

Из c источника в Include / 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

Ответ на комментарии:

Я хотел бы отметить, что это также верно для непустого случая, хотя он довольно уродлив, как l=[]тогда %timeit len(l) != 090,6 нс ± 8,3 нс, %timeit l != []55,6 нс ± 3,09, %timeit not not l38,5 нс ± 0,372. Но никто не получит удовольствия, not not lнесмотря на тройную скорость. Это выглядит смешно. Но скорость выигрывает,
я полагаю, что проблема заключается в тестировании со временем, так как просто if l:достаточно, но неожиданно %timeit bool(l)дает 101 нс ± 2,64 нс. Интересно, что без этого наказания невозможно навязать бул. %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)

Мы можем видеть, что есть немного линейной стоимости для каждого дополнительного 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.

Аарон Холл
источник
Я хотел бы отметить, что это также верно для непустого случая, хотя он довольно уродлив, как l=[]тогда %timeit len(l) != 090,6 нс ± 8,3 нс, %timeit l != []55,6 нс ± 3,09, %timeit not not l38,5 нс ± 0,372. Но никто не получит удовольствия, not not lнесмотря на тройную скорость. Это выглядит смешно. Но скорость выигрывает
Грегори Морс
Я полагаю, что проблема заключается в тестировании со временем, поскольку if l:достаточно, но неожиданно %timeit bool(l)получается 101 нс ± 2,64 нс. Интересно, что без этого наказания невозможно навязать бул. %timeit lбесполезен, так как никакого преобразования не произойдет.
Грегори Морс
139

Пустой список сам по себе считается ложным в тестировании истинного значения (см. Документацию по Python ):

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

@ Дарен Томас

РЕДАКТИРОВАТЬ: Еще одно замечание против проверки пустого списка как False: Как насчет полиморфизма? Вы не должны зависеть от списка, являющегося списком. Он должен просто крякать, как утка - как вы собираетесь заставить свой duckCollection крякать «Ложь», когда в нем нет элементов?

Ваша duckCollection должна реализовать __nonzero__или __len__так, если: будет работать без проблем.

Питер Хоффманн
источник
Странно, как [] == Falseбудет оцениваться, хотя False
information_interchange
@information_interchange Если вы хотите явно проверить правильность значения, используйте bool(). bool([]) == Falseбудет оценивать, Trueкак ожидалось.
augurar
103

Ответ Патрика (принятый) правильный: if not a:это правильный способ сделать это. Правильный ответ Харли Холкомба - это руководство по стилю PEP 8. Но то, что ни один из ответов не объясняет, - это то, почему стоит следовать этой идиоме, даже если вы лично обнаружите, что она недостаточно ясна или сбивает с толку пользователей Ruby или чего-либо еще.

Код Python и сообщество Python имеют очень сильные идиомы. Следование этим идиомам делает ваш код более легким для чтения для всех, кто имеет опыт работы с Python. И когда вы нарушаете эти идиомы, это сильный сигнал.

Это правда, что if not a:он не различает пустые списки от Noneили числового 0, или пустые кортежи, или пустые типы коллекций, созданные пользователем, или пустые созданные пользователем типы не совсем коллекции, или одноэлементный массив NumPy, действующий как скаляры с Falsey ценности и т. д. И иногда важно четко об этом говорить. И в этом случае вы знаете, о чем хотите быть явным, поэтому вы можете проверить именно это. Например, if not a and a is not None:означает «что-нибудь фальшивое, кроме None», а if len(a) != 0:означает «только пустые последовательности - и все, кроме последовательности, является здесь ошибкой», и так далее. Помимо тестирования именно того, что вы хотите проверить, это также сигнализирует читателю, что этот тест важен.

Но когда вам нечего прямо выражать, ничего, кроме того, if not a:что вводит читателя в заблуждение. Вы сигнализируете о чем-то важном, когда это не так. (Вы можете также сделать код менее гибким, или медленнее, или любой другой , но это все , что менее важно.) И если вы постоянно вводить читателя в заблуждение , как это, тогда , когда вы делаете потребность сделать различие, это будет проходить незамеченным , потому что ты был "плачущим волком" по всему твоему коду.

abarnert
источник
78

Зачем вообще проверять?

Похоже, никто не обращался с вопросом о том, нужно ли вам сначала проверять список. Поскольку вы не предоставили никакого дополнительного контекста, я могу себе представить, что вам может не понадобиться делать эту проверку, но вы не знакомы с обработкой списков в Python.

Я бы сказал, что самый питонический способ - это вообще не проверять, а просто обрабатывать список. Таким образом, он будет делать правильные вещи, будь то пустой или полный.

a = []

for item in a:
    <do something with item>

<rest of code>

Это имеет преимущество обработки любого содержимого , не требуя проверки конкретной для пустоты. Если a пусто, зависимый блок не будет выполнен, и интерпретатор перейдет к следующей строке.

Если вам действительно нужно проверить массив на пустоту, других ответов достаточно.

MrWonderful
источник
3
Дело в том, что проверить, является ли список пустым, очень важно, по крайней мере, для меня. Задумывались ли вы, есть ли внутри какой-нибудь скрипт, <rest of code>который может использовать результат forцикла? Или напрямую использовать некоторые значения в a? Действительно, если скрипт предназначен для работы со строго контролируемым вводом, проверка может быть немного ненужной. Но в большинстве случаев входные данные различаются, и проверка обычно бывает лучше.
Амарт Гюль
С уважением, нет. Я подумал, что кто-то, кто недостаточно разбирается в Python, знает, что «если <list>:» является правильным ответом, спрашивает, как проверить пустой список. Затем я замечаю МНОГО ответов, которые предлагают разные мнения, но ни один из них, похоже, не отвечает первоначальной потребности. Вот что я пытался сделать с моим ответом - пусть они изучат необходимость, прежде чем продолжить. Я полагаю, что я предложил так много в своем ответе, явно.
MrWonderful
@ AmarthGûl - Как можно получить результаты цикла for для скрипта внутри <оставшейся части кода> для обработки? В списке, возможно? Или, может быть, дикт? Если так, то применяется та же логика. Я не понимаю, как ввод переменных может иметь какой-либо эффект в любом разумно разработанном коде, где обработка пустого списка была бы плохой идеей.
MrWonderful
Немного старый, но если вы просто проверяли, был ли список пустым, то для непустого списка ваш код повторяет процесс снова и снова, когда OP просто ищет операцию проверки. Просто представьте себе худший сценарий для этого кода, когда n приближается к бесконечности ....
DJK
7
@DJK - Нет, я думаю, что ты все еще скучаешь по этому. Предположительно, вы хотите сделать что-то со списком, если у вас есть. Что бы вы сделали по-другому, если бы он был пустым? Вернуть рано? Что если он не пустой? обработать это? Дело, однако , в том, что вам, вероятно , не нужно проверять пустой список, просто переберите его и сделайте все, что вы собирались сделать с элементами. Если нет элементов, вы проваливаетесь. Если есть элементы, вы обрабатываете их так, как вам нужно. Дело не в том, чтобы использовать пример FOR для пустой проверки, а в том, чтобы вообще НЕ проверять, просто обработать список.
MrWonderful
40

Я написал:

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

за который проголосовали -1. Я не уверен, что это потому, что читатели возражали против стратегии или считали, что ответ не был полезен в представленном виде. Я буду притворяться, что это последнее, поскольку - что бы ни считалось "питоническим" - это правильная стратегия. Если вы уже не исключили или не готовы обрабатывать случаи 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значение, для которого оно не определено), которое вы готовы обработать. В общем, "питонические" соглашения, кажется, идут этим последним путем. Сожмите его, как утку, и дайте ему поднять ошибку DuckError, если он не знает, как крякать. Вы все равно должны это сделать, подумать о том, какие допущения типов вы делаете, и действительно ли ошибки, которые вы не готовы обрабатывать должным образом, будут приводить к ошибкам в нужных местах. Массивы Numpy являются хорошим примером, когда просто слепо полагаться наlen или тип логического типа может не выполнять то, что вы ожидаете.

dubiousjim
источник
3
Довольно редко у вас будет исчерпывающий список из 6 типов, которые вы хотите принять, и не будьте гибкими для других типов. Когда вам нужны такие вещи, вы, вероятно, хотите ABC. В этом случае, вероятно, это будет одна из азбуки stdlib, например collections.abc.Sizedили collections.abc.Sequence, но это может быть та, которую вы пишете себе и register(list)дальше. Если у вас действительно есть код, в котором важно отличать пустой от другого фальши, а также отличать списки и кортежи от любых других последовательностей, то это правильно, но я не верю, что у вас есть такой код.
Абарнерт
13
Причина, по которой людям это не нравится, заключается в том, что в большинстве случаев это совершенно необычно. Python - типизированный утиной язык, и этот уровень защитного кодирования активно этому препятствует. Идея системы типов Python заключается в том, что все должно работать так долго, как объект передается в функциях так, как ему нужно. Делая явные проверки типов, вы заставляете вызывающую сторону использовать определенные типы, что противоречит самой сути языка. Хотя иногда такие вещи необходимы (за исключением того, что строки рассматриваются как последовательности), такие случаи редки и почти всегда лучше, чем черные списки.
Гарет Латти
1
Если вы действительно хотите проверить, что значение точно, []а не что-то ложное, другого типа, тогда, конечно if a == []:же, это нужно, а не копаться в isinstance.
RemcoGerlich
2
==Хотя есть некоторые автоматические принуждения . На макушке головы я не могу определить, для кого []. [] == ()например возвращается False. Но например frozenset()==set()возвращается True. Так что стоит хотя бы немного подумать о том, может ли какой-либо нежелательный тип быть приведен [](или наоборот) при выполнении a == [].
Сомнительный Jim
@RemcoGerlich - isinstance () по-прежнему предпочтительнее, чем создание пустого списка для сравнения. Также, как уже указывалось, оператор равенства может вызывать неявное преобразование некоторых типов, что может быть нежелательным. Нет никакой причины когда-либо кодировать «a == []», и этот код определенно будет помечен как дефект в любом обзоре кода, в котором я принимал участие. Использование соответствующего инструмента, как это предусмотрено языком, не должно рассматриваться как «гадость о "а скорее" хорошая техника программирования ".
MrWonderful
29

Из документации по проверке истинности стоимости:

Все значения, кроме перечисленных здесь, считаются True

  • None
  • False
  • нуль любого числового типа, например, 0, 0.0, 0j.
  • любая пустая последовательность, например, '', (), [].
  • любое пустое отображение, например {}.
  • экземпляры пользовательских классов, если класс определяет метод __bool__()или __len__(), когда этот метод возвращает целочисленный ноль или значение bool False.

Как можно видеть, пустой список []является ложным , поэтому наиболее эффективным представляется то , что будет сделано с логическим значением:

if not a:
    print('"a" is empty!')
Sнаđошƒаӽ
источник
@DJ_Stuffy_K утверждают, что в модульном тестировании пустой список? Просто используйте assert(not myList). Если вы также хотите утверждать, что объект является list, вы можете использовать assertIsInstance().
Снаđошƒаӽ
24

Вот несколько способов проверить, если список пуст:

a = [] #the list

1) Довольно простой питонический способ:

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

В Python пустые контейнеры, такие как списки, кортежи, наборы, запросы, переменные и т. Д., Отображаются как 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")
Inconnu
источник
20

Я предпочитаю следующее:

if a == []:
   print "The list is empty."
Verix
источник
37
Это будет медленнее, так как вы создаете дополнительный пустой список без необходимости.
Карл Мейер
32
это менее читабельно чем if not a:и ломается легче. Пожалуйста, не делай этого.
devsnd
Есть хороший пункт, сделанный ранее () == [], также равный ложному. Хотя мне нравится, как эта реализация читает if not a:все случаи, если вы определенно ожидаете список, тогда вашего примера должно быть достаточно.
Звезда
19

Способ 1 (предпочтительный):

if not a : 
   print ("Empty") 

Способ 2:

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

Способ 3:

if a == [] :
  print ("Empty")
Vikrant
источник
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

Хотя это ничего не стоит, что Noneложно. Так что, если вы не хотите отделить тест на None-несение, вам не нужно этого делать.

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
Tagar
источник
8

Было дано много ответов, и многие из них довольно хороши. Я просто хотел добавить, что проверка

not a

Также будут проходить Noneи другие типы пустых структур. Если вы действительно хотите проверить пустой список, вы можете сделать это:

if isinstance(a, list) and len(a)==0:
    print("Received an empty list")
HackerBoss
источник
Возможно, это вызывает исключение, если aэто не список и aметод не __len__реализован. Я бы порекомендовал:if isinstance(obj, list): if len(obj) == 0: print '...'
Свен Крюгер
4
@ Свенкрюгер Нету. Оператор andленив в Python. Ничто после andне будет выполнено, если условие перед andложно.
ElmoVanKielmo
7

мы могли бы использовать простой, если еще:

item_list=[]
if len(item_list) == 0:
    print("list is empty")
else:
    print("list is not empty")
л. чжан
источник
5
-1 - Чтобы избежать путаницы, не используйте зарезервированные слова для имен переменных, иначе при следующем вызове вы можете получить удивительное поведение, например, list () »... что-то вроде« TypeError: объект list » не вызывается "или что-то подобное.
MrWonderful
6

Если вы хотите проверить, пуст ли список:

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.
Рахул
источник
1
all (bool (x) для x в l) - True для пустого списка
gberger
5

Вдохновленный решением @ 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
АндрейС Щербаков
источник
1
Чрезмерно; это просто вопрос, является ли список пустым, а не является ли что-то пустым итерируемым.
pppery
1
Если бы я не был доволен if a:, это было бы потому, что я хотел исключение, если бы aне был какой-то контейнер. (Быть итеративным также позволяет итераторы, которые не могут быть
Дэвис Херринг,
5
print('not empty' if a else 'empty')

немного более практично:

a.pop() if a else None

и самая короткая версия:

if a: a.pop() 
Андрей Суглобов
источник
4

Начиная с python3 вы можете использовать

a == []

проверить, если список пуст

РЕДАКТИРОВАТЬ: Это работает с python2.7 тоже ..

Я не уверен, почему есть так много сложных ответов. Это довольно ясно и просто

Tessaracter
источник
1
пожалуйста, дайте больше объяснений о том, как это работает без написания "если"?
Ганешдешмух
3
Это не питон, ни полный пример. Кроме того, он создает пустой список каждый раз, когда встречается. Не делай этого.
MrWonderful
@MrWonderful не создает пустой экземпляр каждый раз. Он просто проверяет, является ли существующий список aпустым или нет.
Tessaracter
@MrWonderful Я не понимаю, что делает этоpythonic
Tessaracter
@ganeshdeshmukh, если вы используете a==[]его, напечатает true на терминале python, если a пусто. Иначе это напечатает Ложь. Вы можете использовать это внутри условия if также какif(a==[])
Tessaracter
3

Вы даже можете попробовать использовать bool (), как это

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

Я люблю этот способ проверки списка пуст или нет.

Очень удобно и полезно.

Сунил Люлла
источник
4
Для тех (как я), кто не знал, bool()преобразует переменную Python в логическое значение, так что вы можете хранить истинность или ложность значения, не используя оператор if. Я думаю, что это менее читабельно, чем просто использование условного ответа, такого как принятый ответ, но я уверен, что есть и другие хорошие варианты его использования.
Гален Лонг
Это можно использовать в выражении и является более кратким.
Qneill
3

Просто используйте 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).

Винет Джайн
источник
3
Название is_emptyпредполагает, что оно что-то возвращает. Но если это произойдет, то это будет что-то bool(any_structure), что вы должны использовать вместо этого ( когда вам boolвообще нужно ).
Дэвис Херринг,
4
Почему мы хотим, чтобы вариант bool(также) печатал сообщения на стандартный вывод?
Дэвис Херринг,
@DavisHerring У нас всегда есть два варианта: сначала печатать с использованием функции, а другой - с использованием возвращаемой boolпеременной. Твой выбор. Я пишу оба, чтобы вы могли выбирать между ними.
Vineet Jain
3

Простой способ проверки длины равен нулю.

if len(a) == 0:
    print("a is empty")
Ашик Имран
источник
1

Истинное значение пустого списка Falseтаково, что для непустого списка это так True.

MiloMinderbinder
источник
1

Что привело меня сюда, так это особый вариант использования: я на самом деле хотел, чтобы функция сообщала мне, пустой список или нет. Я хотел избежать написания своей собственной функции или использования лямбда-выражения здесь (потому что казалось, что это должно быть достаточно просто):

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(то есть if bool(L):), потому что это подразумевается. Но для случаев, когда «не пусто» явно требуется как функция, boolэто лучший выбор.

Ведран Шего
источник
1

Чтобы проверить, является ли список пустым или нет, вы можете использовать два следующих способа. Но помните, мы должны избегать способа явной проверки типа последовательности (это 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 True
    else: 
        return False

# ––––––––––––––––––––––––––––––––

list1 = [] 

if enquiry(list1): 
    print ("The list is Empty") 
else: 
    print ("The list isn't empty") 

# Result: "The list is Empty"

Надеюсь это поможет.

Энди
источник