





if not a:
print("List is empty")
Использование неявная логика пустого list довольно питонично.
@JamesMcMahon - это компромисс между явностью и гибкостью типов. как правило, «быть откровенным» означает не делать «волшебных» вещей. с другой стороны, «утиная типизация» означает работу с более общими интерфейсами, а не явную проверку типов. так что что-то вроде if a == [] форсирует определенный тип (() == [] - это False). здесь общий консенсус, похоже, заключается в том, что утиная печать побеждает (по сути, говоря, что __nonzero__ - это интерфейс для тестирования пустоты docs.python.org/reference/datamodel.html#object.__nonzero__)
Этот метод не работает с массивами numpy .. поэтому я думаю, что, если len (a) == 0 предпочтительнее как с точки зрения «утиной печати», так и с точки зрения неявности.
Канонический способ узнать, является ли массив в C пустым, - это разыменовать первый элемент и посмотреть, является ли он нулевым, предполагая, что массив завершается нулем. В противном случае сравнение его длины с нулем совершенно неэффективно, если массив имеет значительный размер. Кроме того, как правило, вы не выделяете память для пустого массива (указатель остается нулевым), поэтому нет смысла пытаться получить его длину. Я не говорю, что len (a) == 0 - не лучший способ сделать это, просто он не кричит мне «C», когда я его вижу.
@sleblanc Я никогда не видел массив с завершающим нулем в c за пределами реализации строки, общий случай - это не завершение нулем. «сравнение его длины с нулем совершенно неэффективно» неверно, не существует реализации c, где это стоило бы больше пары циклов. Сравнение длины массива с 0 для определения пустоты является стандартной практикой в c и почти во всех языках, на которые влияет c (C++, java, C# и т. д.).
@BrennenSprimont, если он не завершается нулем, значит, вы уже знаете длину, хранится ли она в отдельной переменной или ваш массив завернут в какой-то контейнер, который отслеживает длину. C++, Java, C# имеют такие контейнеры и эффективно реализуют некоторый метод "длины". C имеет нет такой вещи, вам придется свернуть свой собственный. Статически выделенные массивы C - это просто указатели на область памяти, в которой гарантированно будет достаточно места для хранения запрошенного вами объема данных. В C нет ничего, что сообщило бы вам, сколько вы уже заполнили это пространство.
Другой аналогичный способ: print (bool(not a))
Если вы используете это для настраиваемого объекта, то есть «if not customObject», убедитесь, что вы реализовали метод len в определении класса настраиваемого объекта, иначе он будет оцениваться как False даже для пустого объекта.
Простая вариация в одну строку: 'Empty' if not a else 'Full' вот так: 'Empty' if not [1] else 'Full'
При использовании Numpy и в соответствии с его документацией вы должны использовать: array.size> 0 В противном случае у вас будет следующее сообщение. DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use array.size > 0 to check that an array is not empty.
Исходя из языка, который претендует на звание своего рода поэзии, этот механизм - чистый мусор. Семантически быть пустым очень отличается от того, чтобы быть пустым.
Мы тоже можем использовать if (len(a) == 0):
@ Mr.WorshipMe: if len(a) == 0 также не работает для массивов NumPy, потому что он не работает для таких фигур, как (5, 0). Массив 5 на 0 пуст, но имеет длину 5. Проверкой массива NumPy будет a.size == 0 (или not a.size), что не работает для списка.
Он напечатает, что a пуст, а a = None считается пустым, потому что not bool(None) == True.
Если кто-то сочтет это полезным, я создал учебное пособие на YouTube, в котором сравниваются различные способы проверить, пуст ли список youtube.com/watch?v=8V88bl3tuBQ
Похоже на разработчика Python, влюбленного в Ruby. ржунимагу
Это неявно и, следовательно, непифонично, поскольку «явное лучше, чем неявное».
if bool([]) #Falseif bool([1,2,3]) #True Мне кажется, проще всего использовать bool(list_name).
@ThunderPhoenix - можно также просто использовать if len (a):, поскольку значение> ноль будет оцениваться как True ... ;-)
Замечательно, что кто-то поднял вопрос, что это неприменимо для массива numpy, но давайте сосредоточимся на вопросе How do I check if a list is empty?. Мы просто хотим проверить, пуст список или нет. Я думаю, что этот ответ хорош и в значительной степени питонический, и я полностью согласен с sleblanc.
Думая об этом, питон уже имеет наши спины, он уже дает нам истинное значение последовательностей, таких как строки, списки, кортежи, как указано ниже. Таким образом, мы можем просто использовать его DIRECTLY и не получать len(), чтобы проверить, является ли он EMPTY.
@andrewcooke Я пришел к выводу, что здесь используется тип утки, потому что он общий и не проверяет тип.
Мне интересно, что вопрос касается проверки того, был ли передан пустой список, и многие непреклонны в том, что решение не должно различать переданный пустой список и переданный None. Или 0 передается. Не зная, какие другие возможные значения могут быть переданы и представляют ли каждое из них отдельный случай, который необходимо обработать, мы не можем предположить, что уместен более широкий тест.
Пустой список сам по себе считается ложным при тестировании истинного значения (см. документация python):
a = []
if a:
print "not empty"
@ Дарен Томас
EDIT: Another point against testing the empty list as False: What about polymorphism? You shouldn't depend on a list being a list. It should just quack like a duck - how are you going to get your duckCollection to quack ''False'' when it has no elements?
Ваша duckCollection должна реализовывать __nonzero__ или __len__, поэтому if: будет работать без проблем.
Странно, как [] == False оценит как False, хотя
@information_interchange Если вы хотите явно проверить истинность значения, используйте bool(). bool([]) == False будет соответствовать True, как и ожидалось.
Я предпочитаю следующее:
if a == []:
print "The list is empty."
Это будет медленнее, поскольку вы создаете лишний пустой список без необходимости.
это менее читабельно, чем if not a:, и легче ломается. Пожалуйста, не делай этого.
Ранее было высказано хорошее мнение, что () == [] также равен false. Хотя мне нравится, как эта реализация читает, if not a: охватывает все случаи, если вы определенно ожидаете список, вашего примера должно быть достаточно.
нужна цитата "легче ломается"? if not a прерывается, когда a является None - вы можете желание такое же поведение для None и [], но если вы явно хотите проверить пустой список, if not a этого не сделает.
Питонический способ сделать это - из Руководство по стилю PEP 8 (где да означает «рекомендуется», а Нет означает «не рекомендуется»):
For sequences, (strings, lists, tuples), use the fact that empty sequences are false.
Yes: if not seq: if seq: No: if len(seq): if not len(seq):
Второй способ кажется лучше, если вы хотите сигнализировать, что seq, как ожидается, будет своего рода списковым объектом.
@BallpointBen, который, как сказали бы сторонники питонизма, должен быть неявным в способе наименования переменной, насколько это возможно.
@BallpointBen попробуйте использовать Python подсказка типа для сигнализации, какой должна быть переменная. Он был представлен в версии 3.5.
numpy нарушил эту идиому ... seq = numpy.array ([1,2,3]), за которым следует if not seq, вызывает исключение "ValueError: истинное значение массива с более чем одним элементом неоднозначно. Используйте a.any () или a.all () "
Несмотря на всех сторонников Pythonic, я поддерживаю @BallpointBen в том, что если вы по ошибке написали seq = [0] как seq = 0, len(seq) поможет вам отловить ошибку. Человеку свойственно ошибаться. Так что программист.
Я только что получил это сообщение при использовании Python 3.6.4: «FutureWarning: поведение этого метода изменится в будущих версиях. Вместо этого используйте специальный тест 'len (elem)' или 'elem is not None'». поэтому я предполагаю, что это четко определяет предпочтение
@jeronimo: Я считаю, что это предупреждение, относящееся к lxml.
@aafulei Загрязнение исходного кода сигналами, помогающими программисту избежать ошибок кодирования, - глупое занятие. Неэлегантное наложение этой неуместной проблемы на исходный код приводит к тому, что код становится труднее читать и следовать, что в течение срока службы кода приводит к появлению большего, а не меньшего количества ошибок. Существуют тесты для решения проблемы (постоянного) обеспечения правильности и для отделения этой проблемы от любых других. Я новичок в Python, кстати, в этих утверждениях нет ничего Pythonic, они отражают основные принципы SRP, которые могут и должны быть выражены на любом данном языке.
@ Mr.WorshipMe, это здорово, что вы поднимаете эту тему с numpy arrays, но мы не говорим здесь о <class 'numpy.ndarray'>, мы говорим о <class 'list'>, хотя оба являются итерациями и в основном массивами, но это не главное.
len() - это операция O (1) для списков, строк, диктовок и наборов Python. Python внутренне отслеживает количество элементов в этих контейнерах.
JavaScript имеет аналогичное понятие правдивости / лжи.
Я предпочитаю это явно:
if len(li) == 0:
print('the list is empty')
Таким образом, на 100% ясно, что li - это последовательность (список), и мы хотим проверить ее размер. Моя проблема с if not li: ... заключается в том, что он создает ложное впечатление, что li является логической переменной.
Проверка того, равна ли длина списка нулю, а не просто проверка того, является ли список ложным, уродлива и непифонична. Любой, кто знаком с Python, не подумает, что li - это булево, и ему все равно. Если это важно, вы должны добавить комментарий, а не код.
Это похоже на излишне точный тест, который часто медленнее и всегда менее читабелен, ИМХО. Вместо того, чтобы проверять размер чего-то пустого, почему бы просто не проверить, пусто ли оно?
В любом случае, причина, по которой это плохо (и что нарушение идиом на языке с сильными идиомами, такими как Python, в целом плохо), заключается в том, что он сигнализирует читателю, что вы специально проверяете длину по какой-то причине (например, потому что вам нужен None или 0, чтобы вызвать исключение вместо передачи). Итак, когда вы делаете это без причины, это вводит в заблуждение - и это также означает, что, когда вашему коду делает необходимо проводить различие, различие невидимо, потому что вы «кричите волк» во всем остальном источнике.
Я считаю, что это просто ненужное удлинение кода. В противном случае, почему бы не быть еще более «явным» с if bool(len(li) == 0) is True:?
@Jabba во многих случаях это будет О (1) (те, где вы работаете со встроенными типами данных), но вы просто не можете полагаться на это. Возможно, вы работаете с настраиваемым типом данных, у которого нет этого свойства. Вы также можете решить добавить этот настраиваемый тип данных позже, после того, как вы уже написали этот код.
Очень плохо хвататься за длину только для проверки на пустоту. Это никуда не годится.
Это анти PEP 8
Что, если вы делать хотите вызвать исключение для типов без __len__? В таком случае это идеально.
Если неясно, что li - это список, возможно, вам не стоило называть его li. Я думаю, что очень мало хороших имен переменных, состоящих всего из двух букв. А как насчет cars или evasive_manoeuvres? С другой стороны, логические значения должны содержать в имени is или has или другой глагол, сравните if is_evasive_manoeuvre: и if evasive_maoeuvres. Мне ясно, что является bool, а какое - коллекцией.
Это как показать другу контейнер, полный 0 апельсинов. Это не контейнер с апельсинами ... и если он не имеет ничего общего с contain ... тогда это вообще можно было бы утверждать, что это контейнер. Он становится контейнером, содержащим содержимое, только после того, как содержимое содержится. (x_x)
По крайней мере, он не скажет, что a пуст для a == None, в то время как not a будет оцениваться как True для a == None.
На мой взгляд, not X решает проблему True для слишком многих возможных случаев X. В частности, пустой список и None. Хотя случай, когда значением является либо пустой список, либо None, вероятно, не произойдет должен, я не уверен, что это буду не произойдет. Особенно, когда другие люди используют части моего кода. Несмотря на то, что это анти-PEP 8, я все же предпочитаю этот подход.
@augurar: Обращаясь к идее, что это просто делает его излишне более явным, стоит отметить, что if bool(len(li) == 0) is True делает то же самое, что и if len(li) == 0, и поэтому нет смысла добавлять этот дополнительный код. Однако if len(li) == 0 определенно делает нечто иное, чем if li. Я думаю, что разумно утверждать, что люди не должны кодировать вещи таким образом, чтобы последнее сравнение давало разные результаты. Однако последнее сравнение может дает другие результаты, тогда как первое сравнение не можешь, поэтому я не думаю, что это хороший аргумент.
@ShianiaWhite неверно, это ужасный способ проверить, является ли len в списке пустым или нет. Нет необходимости вычислять len последовательности, чтобы проверить ее пустоту, у python уже есть наши спины, он легко дает значение истинности последовательности ... так что выполнение if l - в значительной степени лучшее. Представьте себе последовательность размером почти миллион, не хотели бы мы тратить наши жизни, чтобы получить len? Ответ Патрика - лучший.
@StackOffended Временная сложность len в списке - O (1), а не O (n), как вы могли подумать. См. здесь для получения дополнительной информации.
о, это здорово! это поддерживает ваш аргумент, но я думаю, что после 8 лет этой темы выполнение if a по-прежнему будет рекомендовано & pythonic.
@IceBear Используйте то, что хотите. Спустя 8 лет я все еще предпочитаю len(a).
Вау, это потрясающе! Я понимаю, что временная сложность len(a) в качестве примера - O(1). Но для меня я просто считаю, что это pythonic и еще что-то вроде logical для использования if a. Я все еще поражаюсь после того, как 8 слышал, что вы все еще предпочитаете это: D haha
Как разработчику, пришедшему с C / C++, это особенно вредит моему мозгу, и сначала я нашел первый комментарий в этой ветке абсурдным. "Проверка, не является ли список ложным" ??? Что все это значит. Как это вообще понятно программисту? Я ожидал, что что-то вроде not None вернет True - в этом есть смысл. Но объект списка? У него есть тип! Это не пустяк. Это просто свойство Python, что (почти) все встроенные типы предлагают приятную логическую оценку, которая имеет смысл в контексте типа и которую нужно уважать, чтобы быть успешным Pythonista.
This is the first google hit for "python test empty array" and similar queries, plus other people seem to be generalizing the question beyond just lists, so I thought I'd add a caveat for a different type of sequence that a lot of people might use.
Вам нужно быть осторожным с массивами NumPy, потому что другие методы, которые хорошо работают для list или других стандартных контейнеров, не работают для массивов NumPy. Я объясню почему ниже, но вкратце, предпочтительный метод должен использовать size.
«Питонический» способ терпит неудачу с массивами 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()
Но, по крайней мере, приведенный выше случай говорит вам, что это не удалось. Если у вас есть массив 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 дает, чтобы убедиться, что для каждого типа используется правильный тест. Не очень "питонический", но оказывается, что NumPy намеренно нарушил питоничность хотя бы в этом смысле.
Если вам нужно сделать больше, чем просто проверить, является ли ввод пустым, и вы используете другие функции NumPy, такие как индексирование или математические операции, вероятно, более эффективно (и, безусловно, более часто) принудительно вводить быть в массив NumPy. Для быстрого выполнения этой задачи есть несколько хороших функций - самая важная - numpy.asarray. Он принимает ваш ввод, ничего не делает, если он уже является массивом, или обертывает ваш ввод в массив, если это список, кортеж и т. д., И при необходимости преобразует его в выбранный вами dtype. Таким образом, он работает очень быстро, когда это возможно, и гарантирует, что вы просто предполагаете, что ввод - это массив NumPy. Обычно мы даже просто используем то же имя, так как преобразование в массив не вернется за пределы текущего объем:
x = numpy.asarray(x, dtype=numpy.double)
Это заставит проверку x.size работать во всех случаях, которые я вижу на этой странице.
Стоит отметить, что это не недостаток Python, а, скорее, преднамеренный разрыв контракта со стороны numpy - numpy - это библиотека с очень конкретным вариантом использования, и у нее есть другое `` естественное '' определение того, что такое истинность в массиве. стандарту Python для контейнеров. Имеет смысл оптимизировать для этого случая, так как pathlib использует / для объединения путей вместо + - это нестандартно, но имеет смысл в контексте.
Согласовано. Я хочу сказать, что важно помнить, что numpy сделал выбор, чтобы сломать утиную типизацию как для очень распространенных идиом if x, так и для len(x), и иногда эту поломку очень трудно обнаружить и отладить.
Я не знаю, для меня, если метод с именем len (x) не возвращает длину массива из-за предположений, его имя плохо спроектировано.
@Dalton Я не согласен с этой интерпретацией len() для массивов numpy. Если вы конвертируете numpy.zeros((1,0)) в список, вы получите [[]], что является логическим значением true. Массив numpy не пуст, потому что он содержит один (пустой) массив.
@pydsigner Я согласен с вашим выводом, но я буду спорить с вашей логикой, особенно с вашим последним предложением. numpy.zeros((1,0)) определенно не является массивом, содержащим один (пустой) массив; это просто единственный массив, не содержащий элементов. Массивы Numpy не вложены. Когда вы запускаете tolist, вы получаете список, содержащий один (пустой) список, но это совсем другой зверь. С другой стороны, кажется, что len просто дает размер первого измерения массива. Это не неправильный; это просто выбор (хотя я бы его не сделал).
@Mike В то время как str () массива 1x0 - [], запуск for sub in numpy.zeros((1,0)): print sub будет выводить [] как внутренний массив, а не ничего не печатать. Причуда представления массива не должна определять, как мы рассматриваем конструкцию.
Я не уверен, что понимаю вашу точку зрения. Если вы используете print(type(sub)) в своем примере, вы получите <class 'numpy.ndarray'>, а не list. Во всяком случае, это не имеет значения, потому что это просто означает, что они реализовали итерацию. В этом нет никакой причуды: от их интерфейса на уровне Python до реализации C API, вплоть до их размещения в памяти, массивы numpy являются многомерными массивами, а не вложенными массивами или списками. Вы можете разрезать их для извлечения подмассивов, но это не имеет ничего общего с вложенностью.
Этот вопрос не имеет ничего общего с массивами numpy
@ppperry Да, исходный вопрос не касался массивов Numpy, но при работе с этими и, возможно, типизированными аргументами этот вопрос становится очень актуальным.
Способ нимпифонический на случай, если вы также хотите заставить свой код работать, если указан список, - это сначала принудительно ввести любой возможный ввод в массив numpy с помощью asarray. После этого вы можете продолжить, как в своем ответе, не беспокоясь о других форматах.
@BasSwinckels Хорошее замечание. Я предполагаю, что не всегда стоит прилагать усилия, если задача Только, которую вы хотите сделать, - это проверить, пуст ли ввод, но, безусловно, это то, что мы обычно делаем, когда действительно хотим что-то сделать с вводом. Я добавлю это к своему ответу. Спасибо.
«len (numpy.zeros ((1,0))) возвращает 1, даже если в массиве ноль элементов». Это IMO не сильно отличается от списка, содержащего пустой список. оба имеют len 1 и приводят к одной итерации, когда вы их перебираете.
@plugwash Об этом говорилось выше, поэтому я просто повторю, что все остальное о numpy - от кода C до других аспектов его высокоуровневого интерфейса - говорит о том, что массив определенно является нет вложенным типом объекта; это единый многомерный объект. То есть numpy.zeros((1,0)) не должен рассматриваться как массив, содержащий другой массив (который просто оказывается пустым). Вместо этого его следует рассматривать как единый двумерный массив, не содержащий элементов. И в результате вам нужно помнить о различии всякий раз, когда вы проверяете пустой массив.
@GarethLatty: совсем нет. / может применяться только между Path и str или объектами, подобными пути. И это питонический очень, поскольку Python - язык со строгой типизацией. Кроме того, + кажется скорее конкатенацией между строками, и это нет поведение объединения путей (попробуйте, например, Path("a") / "b/"). Наконец, много более элегантен для соединения путей с /. Напротив, numpy реализовал операторы между кошками и собаками. Таким образом, они полностью нарушили любой контракт Python.
@GarethLatty: например, если я хочу создать функцию, которая может принимать любую итерацию, и мне нужно использовать bool() или len(), я вынужден проверять, является ли итерация ndarray, и угрожать ей другим способом. Так куда делась утиная машинка? Утку съел numpy, жаждущий привлечь пользователей Matlab :-D
Если len(zeros((1,0)) вернул 0, то len(zeros((2,2)) должен вернуть 4. Для этого есть метод size. Если array.shape - это (2,3,4), то array[1].shape - это (3,4), что означает, что первое измерение работает как контейнер для конечных измерений и т. д., Точно так же, как вложенный список. Так что ожидаемый результат len(array) наверняка - array.shape[0]. А zeros((1,0)) что-то содержит: он содержит одно конечное измерение с экстентом 0.
Я написал:
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 или логического преобразования типов может не дать именно того, что вы ожидаете.
Довольно редко у вас будет исчерпывающий список из 6 типов, которые вы хотите принять и не будете гибкими для каких-либо других типов. Когда вам нужны такие вещи, вы, вероятно, захотите азбуку. В этом случае, вероятно, это будет одна из ABC stdlib, например collections.abc.Sized или collections.abc.Sequence, но это может быть та, которую вы пишете сами и на которой register(list). Если у вас действительно есть код, в котором важно отличать пустые значения от других ложных, а также отличать списки и кортежи от любых других последовательностей, тогда это правильно, но я не верю, что у вас есть такой код.
Причина, по которой людям это не нравится, заключается в том, что в большинстве случаев это совершенно бессмысленно. Python - это язык с утиным типом, и этот уровень защитного кодирования активно этому препятствует. Идея системы типов Python заключается в том, что все должно работать до тех пор, пока объект передается в функциях так, как ему нужно. Выполняя явную проверку типов, вы заставляете вызывающую сторону использовать определенные типы, что противоречит самой сути языка. Хотя иногда такие вещи необходимы (исключение обработки строк как последовательностей), такие случаи редки и почти всегда лучше всего занести в черные списки.
Если вы действительно хотите проверить, является ли значение именно [], а не чем-то ложным другого типа, тогда, безусловно, требуется if a == []:, а не возиться с isinstance.
Тем не менее, для == есть несколько автоматических принудительных действий. Совершенно верно, я не могу определить ни одного для []. Например, [] == () возвращает False. Но, например, frozenset()==set() возвращает True. Так что стоит хотя бы немного подумать о том, может ли какой-то нежелательный тип быть приведен к [] (или наоборот) при выполнении a == [].
@RemcoGerlich - isinstance () по-прежнему предпочтительнее, чем создание пустого списка для сравнения. Кроме того, как указывал другой, оператор равенства может вызывать неявное преобразование некоторых типов, что может быть нежелательным. Нет причин когда-либо кодировать "a == []", и этот код определенно будет отмечен как дефект в любой проверке кода, в которой я участвовал. Использование соответствующего инструмента, предоставляемого языком, не должно рассматриваться как "заблуждение о , "а скорее" хорошая техника программирования ".
Вместо того, чтобы вручную проверять типы, вы должны использовать подсказка типа (введено в 3.5).
Подсказки @Boris Type помогают средствам проверки статического типа (например, mypy) проверять правильность типа, но не выполняют проверку типа во время выполнения.
Патрик (принят) ответ прав: if not a: - правильный способ сделать это. Ответ Харли Холкомба прав, что это в руководстве по стилю 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:, вводит читателя в заблуждение. Вы сигнализируете о чем-то столь же важном, когда это не так. (Вы также можете сделать код менее гибким, или более медленным, или что-то еще, но это все менее важно.) И если вы так обычно вводите читателя в заблуждение, тогда, когда вам делать необходимо провести различие, это пройдет незамеченным, потому что вы были "плачущим волком" на протяжении всего кода.
«И когда вы нарушаете эти идиомы, это сильный сигнал». Это может быть сильным сигналом того, что вы просто работаете с кодом, написанным кем-то, кто плохо знаком с python, а это много людей.
Похоже, никто не задавал вопросов вашему необходимость, чтобы в первую очередь проверить список. Поскольку вы не предоставили никакого дополнительного контекста, я могу представить, что вам, возможно, вообще не нужно выполнять эту проверку, но вы не знакомы с обработкой списков в Python.
Я бы сказал, что способ самый питонический - это вообще не проверять, а просто обрабатывать список. Таким образом, он будет делать все правильно, будь то пустой или полный.
a = []
for item in a:
<do something with item>
<rest of code>
Это дает преимущество обработки любого содержимого а, при этом не требуя специальной проверки на пустоту. Если а пусто, зависимый блок не будет выполняться, и интерпретатор перейдет к следующей строке.
Если вам действительно нужно проверить массив на пустоту, других ответов будет достаточно.
Дело в том, что проверить, пуст ли список, очень важно, по крайней мере, для меня. Задумывались ли вы, есть ли внутри <rest of code> какой-нибудь скрипт, который может использовать результат цикла for? Или напрямую использовать какие-то значения в a? Действительно, если сценарий предназначен для запуска со строго контролируемым вводом, проверка может быть немного ненужной. Но в большинстве случаев входные данные меняются, и обычно лучше иметь чек.
С уважением, нет. Я считал, что кто-то недостаточно разбирается в Python, чтобы знать, что «if <list>:» - правильный ответ, спрашивает, как проверить наличие пустого списка. Затем я замечаю МНОГО ответов, в которых высказывались разные мнения, но ни один из них, похоже, не отвечал первоначальной потребности. Вот что я попытался сделать со своим ответом - попросить их изучить потребность, прежде чем продолжить. Я полагаю, что прямо высказал это в своем ответе.
@ AmarthGûl - Как можно получать обработать результаты из цикла for скрипту внутри <остальной части кода>? Может быть, в списке? А может дикт? Если да, то применима та же логика. Я не понимаю, как ввод переменных может иметь какой-либо эффект в любом виде разумно спроектированного кода, где обработка пустого списка была бы плохой идеей.
Немного устарел, но если бы вы просто проверяли, был ли список пустым, для непустого списка ваш код повторяет процесс снова и снова, когда OP просто ищет операцию проверки. Только представьте себе худший сценарий для этого кода, когда n приближается к бесконечности ....
@DJK Я считаю, что вы, возможно, упустили суть, но для пустого списка код проваливается. Для непустого списка вы просто обрабатываете каждый элемент по мере необходимости. Дело было в том, что «в большинстве случаев проверка на пустоту не требуется». Это вдвойне так, потому что OP не знал, что «if a_list:» был правильным ответом, поэтому потенциально был начинающим разработчиком Python.
Нет, вы создали ошибку O (n) по чеку. вы только рассматриваете хороший результат в пустом списке. Ответ работает, но, на мой взгляд, он неоптимален.
@DJK - Нет, я думаю, тебе все еще не хватает этого. Предположительно, вы хотите что-то сделать со списком, если он у вас есть. Что бы вы сделали иначе, если бы он был пуст? Вернуться раньше? Что делать, если он не пустой? обработать это? Дело в том, что вам не нужно проверять наверное на пустой список, просто перебирайте его и делай то, что собирался делать с элементами. Если нет элементов, вы проваливаетесь. Если есть элементы, вы их обрабатываете как нужно. Дело НЕ в том, чтобы использовать пример для пустой проверки, а в том, чтобы НЕ проверять вообще, просто обработайте список.
Из документация о проверке истинности:
Все значения, кроме перечисленных здесь, считаются True.
NoneFalse0, 0.0, 0j.'', (), [].{}.__bool__() или __len__(), когда этот метод возвращает целое число ноль или логическое значение False.Как видно, пустой список [] - это фальшивка, поэтому выполнение того, что было бы сделано с логическим значением, звучит наиболее эффективно:
if not a:
print('"a" 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 и пустоту по отдельности, поскольку это два разных состояния. Приведенный выше код дает следующий результат:
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
ИМХО, это лучший ответ. Учитываются нюансы применительно к None и [] (пустой список) при тестировании.
Вы даже можете попробовать использовать bool() вот так. Хотя это, безусловно, менее читабельно, это краткий способ сделать это.
a = [1,2,3];
print bool(a); # it will return True
a = [];
print bool(a); # it will return False
Мне нравится этот способ, потому что контрольный список пуст или нет.
Очень удобно и полезно.
Для тех (вроде меня), кто не знал, bool() преобразует переменную Python в логическое значение, поэтому вы можете хранить правду или ложь значения без использования оператора if. Я думаю, что это менее читабельно, чем просто использовать условное выражение, такое как принятый ответ, но я уверен, что для него есть и другие хорошие варианты использования.
Это можно использовать в выражениях и является более кратким.
Обратной стороной является a is None. Часто это приемлемо, но стоит знать об этом.
Вот несколько способов проверить, пуст ли список:
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")
Вдохновленный решением @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
Overbroad; это просто вопрос, пуст ли список, а не является ли что-то пустым итерабельным.
Если меня не устраивает if a:, то это потому, что мне нужно исключение, если a не является чем-то вроде контейнера. (Наличие повторяемый также позволяет использовать итераторы, которые бесполезно тестировать на пустоту.)
Best way to check if a list is empty
For example, if passed the following:
a = []How do I check to see if a is empty?
Поместите список в логический контекст (например, с оператором if или while). Он проверит False, если он пуст, и True в противном случае. Например:
if not a: # do this!
print('a is an empty list')
PEP 8, официальное руководство по стилю Python для кода Python в стандартной библиотеке Python, утверждает:
For sequences, (strings, lists, tuples), use the fact that empty sequences are 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 поддерживает эту семантику непосредственно в интерфейсе объекта списка с помощью логического принуждения.
Из документы (особенно обратите внимание на включение пустого списка []):
By default, an object is considered true unless its class defines either a
__bool__()method that returnsFalseor a__len__()method that returns zero, when called with the object. Here are most of the built-in objects considered false:
- constants defined to be false:
NoneandFalse.- zero of any numeric type:
0,0.0,0j,Decimal(0),Fraction(0, 1)- empty sequences and collections:
'',(),[],{},set(),range(0)
И документация по модели данных:
Called to implement truth value testing and the built-in operation
bool(); should returnFalseorTrue. When this method is not defined,__len__()is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither__len__()nor__bool__(), all its instances are considered true.
и
Called to implement the built-in function
len(). Should return the length of the object, an integer >= 0. Also, an object that doesn’t define a__bool__()method and whose__len__()method returns zero is considered to be false in a Boolean context.
Итак, вместо этого:
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')
Это окупается? (Обратите внимание, что чем меньше времени на выполнение эквивалентной операции, тем лучше :)
>>> 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
This is an extension of
PyObjectthat adds theob_sizefield. This is only used for objects that have some notion of length. This type does not often appear in the Python/C API. It corresponds to the fields defined by the expansion of thePyObject_VAR_HEADmacro.
Из источника 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
I would point out that this is also true for the non-empty case though its pretty ugly as with
l=[]then%timeit len(l) != 090.6 ns ± 8.3 ns,%timeit l != []55.6 ns ± 3.09,%timeit not not l38.5 ns ± 0.372. But there is no way anyone is going to enjoynot not ldespite triple the speed. It looks ridiculous. But the speed wins out
I suppose the problem is testing with timeit since justif l:is sufficient but surprisingly%timeit bool(l)yields 101 ns ± 2.64 ns. Interesting there is no way to coerce to bool without this penalty.%timeit lis useless since no conversion would occur.
Магия 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) != 0 90,6 нс ± 8,3 нс, %timeit l != [] 55,6 нс ± 3,09, %timeit not not l 38,5 нс ± 0,372. Но никому не понравится not not l, несмотря на тройную скорость. Это выглядит смешно. Но скорость побеждает
Я полагаю, проблема заключается в тестировании с помощью timeit, поскольку достаточно только if l:, но на удивление %timeit bool(l) дает 101 нс ± 2,64 нс. Интересно, что без этого штрафа невозможно принудительно использовать bool. %timeit l бесполезен, так как преобразование не произойдет.
Лучший ответ на данный момент, спасибо! Указание на истинную логику Python с помощью магических методов и «Python написан на C; он использует свою логику на уровне C. Все, что вы напишете на Python, будет медленнее. И это, вероятно, будет на несколько порядков медленнее» является ключевым моментом. иначе человек попадает в «предпочтения» и никогда не приходит к правильному выводу.
Большой! Это лучший ответ! Всем, кто читает с 2020 года (это декабрь, значит, уже почти 2021 год) и в будущем. Выполнение if l - это "питонический" способ и ЛУЧШИЙ способ, так как этот парень очень хорошо это объясняет, а также предоставил некоторый образец кода временной производительности, рассчитанной для каждого предлагаемого ответа, а именно if len(a) == 0, if [] == [] и if a. Итак, ясно, что это (if a) намного быстрее и тот, который нужно практиковать!
Просто используйте 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).
Название is_empty предполагает, что он что-то возвращает. Но если бы это было так, то это был бы просто bool(any_structure), который вы должны использовать вместо него (когда вам вообще нужен bool).
Зачем нам нужен вариант bool, который (также) выводит сообщения на стандартный вывод?
@DavisHerring У нас всегда есть два варианта: сначала напечатать с помощью функции, а другой - с помощью возвращаемой переменной bool. Твой выбор. Я пишу оба, чтобы вы могли выбирать между ними.
Если вы хотите проверить, пуст ли список:
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.
all (bool (x) for x in l) истинно для пустого списка
Значение истинности пустого списка - False, тогда как для непустого списка - True.
Простой способ - проверить, что длина равна нулю.
if len(a) == 0:
print("a is empty")
Было дано много ответов, и многие из них довольно хороши. Я просто хотел добавить, что чек
not a
также пройдет для None и других типов пустых структур. Если вы действительно хотите проверить пустой список, вы можете сделать это:
if isinstance(a, list) and len(a)==0:
print("Received an empty list")
Возможно, это вызовет исключение, если a не является списком, а a не имеет реализованного метода __len__. Я бы порекомендовал: if isinstance(obj, list): if len(obj) == 0: print '...'
@ SvenKrüger нет. Оператор and в Python ленив. Ничто после and не будет выполняться, если условие перед and имеет значение False.
print('not empty' if a else 'empty')
немного практичнее:
a.pop() if a else None
и шертестая версия:
if a: a.pop()
Начиная с python3, вы можете использовать
a == []
чтобы проверить, пуст ли список
Обновлено: это тоже работает с python2.7 ..
Не знаю, почему так много сложных ответов. Это довольно ясно и просто
пожалуйста, дайте больше объяснений о том, как это работает, не написав «если»?
Это не питонический и не полный пример. Кроме того, он создает пустой список каждый раз, когда он встречается. Не делай этого.
@MrWonderful он не создает каждый раз пустой список. Он просто проверяет, пуст ли существующий список a.
@MrWonderful Я не понимаю, что делает его pythonic
@ganeshdeshmukh, если вы используете a==[], он будет печатать true на терминале python, если a пуст. В противном случае он напечатает False. Вы можете использовать это внутри условия if также как if (a==[])
To check whether a list is empty or not you can use two following ways. But remember, we should avoid the way of explicitly checking for a type of sequence (it's a
less pythonicway):
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".
The second way is a
more pythonicone. This method is an implicit way of checking and much more preferable than the previous one.
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"
Надеюсь это поможет.
Проголосовали за то, что также показали, как проверить, не пусто ли оно! Это помогает охватить противоположный, но не менее важный вариант использования.
Обратите внимание, что второй может не работать с другими объектами распространенного типа массива, такими как массивы numpy.
мы могли бы использовать простое if else:
item_list=[]
if len(item_list) == 0:
print("list is empty")
else:
print("list is not empty")
-1 - Чтобы избежать путаницы, не используйте зарезервированные слова для имен переменных, иначе вы можете получить неожиданное поведение в следующий раз, когда попытаетесь вызвать, например, "list ()" ... что-то вроде "TypeError: 'list' object is не вызывается "или что-то в этом роде.
Метод 1 (предпочтительный):
if not a :
print ("Empty")
Способ 2:
if len(a) == 0 :
print( "Empty" )
Способ 3:
if a == [] :
print ("Empty")
Что привело меня сюда, так это особый случай использования: я действительно хотел, чтобы функция сообщал мне, пуст список или нет. Я хотел избежать написания собственной функции или использования здесь лямбда-выражения (потому что казалось, что это должно быть достаточно просто):
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 - лучший выбор.
Играя в адвоката дьявола. Я не понимаю, почему эта идиома считается питонической. «Явное лучше, чем неявное», верно? Эта проверка не кажется очень точной в отношении того, что именно проверяется.