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


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

a = []

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


2649


источник


Ответы:


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

Использование неявной логичности пустого списка довольно питоновское.


3801



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

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

Да:  if not seq:
     if seq:

Нет:   if len(seq):
     if not len(seq):

842



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

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

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


500



Другие люди, похоже, обобщают вопрос, выходящий за рамки списков, поэтому я подумал, что добавлю оговорку для другого типа последовательности, которую могут использовать многие люди, тем более, что это первый хит Google для «пустого массива python», ,

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

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

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

«Pythonic» способ выходит из строя с массивами 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, хотя массив имеет нулевые элементы.

Неожиданно

Как объясняется в 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 намеренно сломал питоничность, по крайней мере, в этом смысле.

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

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

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


198



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

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

@ Daren Thomas

EDIT: Еще один момент против тестирования   пустой список: False: как насчет   полиморфизм? Вы не должны зависеть от   список - список. Он должен просто   шарлатан как утка - как ты собираешься   получить утку   «Неверно», когда у него нет элементов?

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


98



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

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

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

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


80



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

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

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

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

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

  • константы, определенные как ложные: 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поле. Это используется только для объектов, которые имеют некоторое понятие длины. Этот тип не часто появляется в API Python / C. Это соответствует полям, определяемым расширением 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

Мне понравилось исследовать это, и я много времени уделяю своим ответам. Если вы думаете, что я оставляю что-то, пожалуйста, дайте мне знать в комментарии.


71



I have seen the below as preferred:

if not a:
    print("The list is empty or null")

61



Why check at all?

No one seems to have addressed questioning your need to test the list in the first place. Because you provided no additional context, I can imagine that you may not need to do this check in the first place, but are unfamiliar with list processing in Python.

I would argue that the most pythonic way is to not check at all, but rather to just process the list. That way it will do the right thing whether empty or full.

a = []

for item in a:
    <do something with item>

<rest of code>

This has the benefit of handling any contents of a, while not requiring a specific check for emptiness. If a is empty, the dependent block will not execute and the interpreter will fall through to the next line.

If you do actually need to check the array for emptiness, the other answers are sufficient.


48



len() is an O(1) operation for Python lists, strings, dicts, and sets. Python internally keeps track of the number of elements in these containers.

JavaScript has a similar notion of truthy/falsy.


44



I had written:

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

which was voted -1. I'm not sure if that's because readers objected to the strategy or thought the answer wasn't helpful as presented. I'll pretend it was the latter, since---whatever counts as "pythonic"---this is the correct strategy. Unless you've already ruled out, or are prepared to handle cases where a is, for example, False, you need a test more restrictive than just if not a:. You could use something like this:

if isinstance(a, numpy.ndarray) and not a.size:
    do_stuff
elif isinstance(a, collections.Sized) and not a:
    do_stuff

the first test is in response to @Mike's answer, above. The third line could also be replaced with:

elif isinstance(a, (list, tuple)) and not a:

if you only want to accept instances of particular types (and their subtypes), or with:

elif isinstance(a, (list, tuple)) and not len(a):

You can get away without the explicit type check, but only if the surrounding context already assures you that a is a value of the types you're prepared to handle, or if you're sure that types you're not prepared to handle are going to raise errors (e.g., a TypeError if you call len on a value for which it's undefined) that you're prepared to handle. In general, the "pythonic" conventions seem to go this last way. Squeeze it like a duck and let it raise a DuckError if it doesn't know how to quack. You still have to think about what type assumptions you're making, though, and whether the cases you're not prepared to handle properly really are going to error out in the right places. The Numpy arrays are a good example where just blindly relying on len or the boolean typecast may not do precisely what you're expecting.


27



Python is very uniform about the treatment of emptiness. Given the following:

a = []

.
.
.

if a:
   print("List is not empty.")
else:
   print("List is empty.")

You simply check list a with an "if" statement to see if it is empty. From what I have read and been taught, this is the "Pythonic" way to see if a list or tuple is empty.


24