Як перевірити, чи список порожній?


3234

Наприклад, якщо було передано наступне:

a = []

Як перевірити, чи aє порожнім?

Відповіді:


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

Використання неявної буленості порожнього listє досить пітонічним.


1128
Граючи захисника диявола. Я не розумію, чому ця ідіома вважається пітонічною. "Явне краще, ніж неявне", правильно? Цей чек не видається явним щодо того, що таке перевірка.
Джеймс Макмахон

222
@JamesMcMahon - це компроміс між явністю та гнучкістю типу. як правило, "бути явним" означає не робити "магічних" речей. з іншого боку, "набирання качок" означає роботу з більш загальними інтерфейсами, а не явну перевірку типів. тому щось подібне if a == []примушує певний тип ( () == []є False). тут загальний консенсус, здається, виграє качка (фактично кажучи, що __nonzero__це інтерфейс для тестування порожнечі docs.python.org/reference/datamodel.html#object.__nonzero__ )
andrew cooke

38
Цей метод не працює на numpy масивах .. тому я думаю, що якщо len (a) == 0 є кращим як з точки зору "набору качок", так і з прихованості.
Mr.WorshipMe

10
Канонічний спосіб дізнатися, чи є масив у C порожнім, - шляхом вилучення першого елемента та перевірки, чи він є нульовим, припускаючи масив, який скасовується на нуль. В іншому випадку порівняння його довжини до нуля є абсолютно неефективним, якщо масив має значні розміри. Також, як правило, ви б не виділяли пам'ять для порожнього масиву (вказівник залишається нульовим), тому не має сенсу намагатися отримати його довжину. Я не кажу, що len (a) == 0 - це не гарний спосіб зробити це, він просто не кричить на мене "C", коли я бачу це.
sleblanc

6
@BrennenSprimont, Якщо це не з нульовим завершенням, то ви вже знаєте довжину, чи зберігається вона в окремій змінній, або ваш масив загортається в якийсь контейнер, який відстежує довжину. У C ++, Java, C # є такі контейнери і ефективно реалізують певний метод "довжини". У C такого не буває, ти повинен прокатати своє. Статично виділені масиви С - це лише покажчики на простір пам'яті, який гарантовано має достатньо місця для зберігання кількості запитуваних вами даних. Немає нічого вбудованого в C, що не дозволить вам знати, скільки ви вже заповнили простір
sleblanc

1158

Пітонічний спосіб зробити це з посібника зі стилю PEP 8 (де Так означає "рекомендується", а Ні - не "Не рекомендується"):

Для послідовностей (рядки, списки, кортежі) використовуйте той факт, що порожні послідовності є хибними.

Yes: if not seq:
     if seq:

No:  if len(seq):
     if not len(seq):

49
Другий спосіб здається кращим, якщо ви хочете подати сигнал, який, seqяк очікується, є якимось об'єктом, подібним до списку.
BallpointBen

5
@BallpointBen, який, як би сказали прихильники Pythonism, повинен бути неявним у тому, як саме названа змінна
аксолотль,

9
@BallpointBen спробуйте використовувати підказку типу Python для сигналізації, якою має бути змінна. Він був введений в 3.5.
Борис

8
numpy порушив цю ідіому ... seq = numpy.array ([1,2,3]), за яким слідує, якщо не, з'являється виняток "ValueError: Значення істинності масиву з більш ніж одним елементом неоднозначне. Використовуйте a.any () або a.all () "
Mr.WorshipMe

2
@jeronimo: Я вважаю, що це специфічне для lxml попередження.
Харлі Холкомб

767

Я віддаю перевагу явно:

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

Таким чином, на 100% зрозуміло, що liце послідовність (список), і ми хочемо перевірити її розмір. Моя проблема if not li: ...полягає в тому, що вона створює помилкове враження, що liє булевою змінною.


91
Перевірка, чи довжина списку дорівнює нулю, а не просто перевірка, чи список неправдивий, некрасивий і непітонічний. Кожен, хто знайомий з Python, не подумає, що liце взагалі буль і не піклується про нього. Якщо це важливо, слід додати коментар, а не більше коду.
Карл Сміт

21
Це здається непотрібним точним тестом, який часто повільніше і завжди менш читабельний IMHO. Замість того, щоб перевіряти розмір чогось порожнього, чому б не просто перевірити, чи він порожній?
Джон Б

34
У будь-якому випадку, причина цього погана (а також те, що порушення ідіом у мові з сильними ідіомами, як Python, погано загалом) полягає в тому, що вона сигналізує читачеві, що ви певно перевіряєте довжину з якихось причин (наприклад, тому, що ви хочете Noneабо 0підняти виняток, а не проходити). Отже, коли ви робите це без причини, що це вводить в оману, і це також означає , що , коли ваш код робить потреба зробити відмінність, відмінність невидимо , бо ви «кричав вовк» в усьому іншому джерела.
abarnert

18
Я думаю, що це просто зайве подовження коду. Інакше, чому б не бути ще «явнішим» if bool(len(li) == 0) is True:?
аугурар

11
@Jabba це буде O (1) у багатьох випадках (тих, де ви працюєте із вбудованими типами даних), але ви просто не можете на це покладатися. Можливо, ви працюєте зі спеціальним типом даних, у якого немає цього властивості. Ви також можете вирішити додати цей спеціальний тип даних пізніше, після того як ви вже написали цей код.
ralokt

324

Це перший хіт 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, навіть якщо масив має нульові елементи.

Нумепітонічний спосіб

Як пояснено у FAQ щодо SciPy , правильним методом у всіх випадках, коли ви знаєте, що у вас є масив NumPy, є ​​використання if x.size:

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

Якщо ви не впевнені, чи може це бути a list, масив NumPy чи щось інше, ви можете поєднати цей підхід з відповіддю, який @dubiousjim дає, щоб переконатися, що правильний тест використовується для кожного типу. Не дуже "пітонічний", але виявляється, що NumPy навмисно зламав пітонічність принаймні в цьому сенсі.

Якщо вам потрібно зробити більше, ніж просто перевірити, чи вхід порожній, і ви використовуєте інші функції NumPy, такі як індексація чи математичні операції, можливо, це більш ефективно (і, звичайно, більш часто), щоб змусити вхід бути NumPy масивом. Існує кілька приємних функцій для цього швидко - найголовніше numpy.asarray. Це забирає ваш вхід, нічого не робить, якщо це вже масив, або завершує ваш вхід у масив, якщо це список, кортеж тощо, і необов'язково перетворює його на обраний вами dtype. Тому це дуже швидко, коли це може бути, і це гарантує вам просто припустити, що вхід є масивом NumPy. Зазвичай ми навіть просто використовуємо те саме ім'я, оскільки перетворення в масив не призведе до того, що воно не виходить за межі поточної області :

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

Це змусить x.sizeперевірити роботу у всіх випадках, які я бачу на цій сторінці.


62
Варто зазначити, що це не хиба в Python, а навмисна розірвання договору numpy- numpyце бібліотека з дуже конкретним випадком використання, і вона має інше «природне» визначення того, що правдивість масиву є для Пітон стандарт для контейнерів. Є сенс оптимізувати для цього випадку таким чином, який pathlibвикористовує /для об'єднання шляхів замість +- це нестандартно, але має сенс у контексті.
Гарет Летті

9
Домовились. Моя думка полягає лише в тому, що важливо пам’ятати, що нумі зробив вибір, щоб порушити набрання качок як для самих поширених, так if xі для len(x)ідіом, - а іноді цей злом може бути дуже важким для виявлення та налагодження.
Майк

22
Я не знаю, якщо метод під назвою len (x) не повертає довжину масиву через припущення, його ім'я погано розроблене.
Далтон

11
Це питання не має нічого спільного з numpy масивами
pppery

19
@ppperry Так, оригінальне питання стосувалося не масивів Numpy, але при роботі з тими і, можливо, аргументованими качками аргументами це питання стає дуже актуальним.
peterhil

223

Найкращий спосіб перевірити, чи список порожній

Наприклад, якщо було передано наступне:

a = []

Як я перевіряю, чи є порожнім?

Коротка відповідь:

Розмістіть список у бульовому контексті (наприклад, з оператором ifабо while). Він перевірить, Falseчи порожній він, Trueінакше. Наприклад:

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

PEP 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.

Але ми вважаємо це непітонічним, оскільки 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

Докази з джерела та документації С

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

Відповідь на коментарі:

Я зазначу, що це справедливо і для не порожнього випадку, хоча його досить потворно, як і 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 написаний на С; вона використовує свою логіку на рівні С. Все, що ви пишете на 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марно, оскільки не відбудеться перетворення.
Григорій Морз

138

Сам порожній список вважається помилковим при тестуванні на справжнє значення (див. Документацію на python ):

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

@Daren Thomas

EDIT: Ще один момент проти тестування порожнього списку як False: А як щодо поліморфізму? Ви не повинні залежати від списку, який є списком. Він повинен просто хитатися, як качка - як ти збираєшся отримати свою duckCollection, щоб збивати "False", коли у неї немає елементів?

Ваш duckCollection повинен реалізувати __nonzero__або __len__так, якщо a: буде працювати без проблем.


Дивно, як [] == Falseоцінюватимете False, хоч
інформація_змін

@information_interchange Якщо ви хочете чітко перевірити правдивість значення, використовуйте bool(). bool([]) == Falseоцінюватимемо, Trueяк очікувалося.
серпень

103

Відповідь Патріка (прийнята) правильна: 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:оману читача. Ти сигналізуєш про щось таке важливе, коли це не так. (Ви можете також зробити код менш гнучким, або повільніше, або будь-який інший , але це все , що менш важливо.) І якщо ви постійно вводити читача в оману , як це, тоді , коли ви робите потреба зробити відмінність, це буде проходити непоміченим , тому що ви "плакали вовка" по всьому коду.


78

Навіщо взагалі перевіряти?

Здається, ніхто не звертався до сумнівів у вашій необхідності перевірити список. Оскільки ви не надали додаткового контексту, я можу уявити, що вам, можливо, не потрібно робити цю перевірку в першу чергу, але ви не знайомі з обробкою списку в Python.

Я б заперечував, що найбільш пітонічний спосіб - це взагалі не перевіряти, а просто обробляти список. Таким чином він зробить правильно, будь то порожній або повний.

a = []

for item in a:
    <do something with item>

<rest of code>

Це має перевагу обробки будь-якого контенту , не вимагаючи перевірки конкретної для порожнечі. Якщо порожньо, залежний блок не буде виконуватися , і інтерпретатор провалиться до наступного рядка.

Якщо вам дійсно потрібно перевірити масив на порожнечу, інших відповідей достатньо.


3
Справа в тому, що перевірка, чи список порожній є досить важливим, принаймні для мене. Ви думали, чи є якийсь скрипт всередині, <rest of code>який може використовувати результат з forциклу? Або безпосередньо використовувати деякі значення в a? Дійсно, якщо сценарій призначений для роботи зі строго контрольованим входом, перевірка може бути трохи зайвою. Але в більшості випадків вхід варіюється, і перевірити зазвичай краще.
Амарт Гюл

З повагою, ні. Я вважав, що хтось недостатньо знає про Python, щоб знати, що "якщо <список>:" була правильною відповіддю, запитала, як перевірити порожній список. Тоді я помічаю багато відповідей, які пропонували різні думки, але жодна з них, здавалося, не задовольняла первісну потребу. Це те, що я намагався зробити зі своєю відповіддю - запропонувати їм вивчити потребу, перш ніж продовжувати. Я вважаю, що я запропонував стільки ж у своїй відповіді, чітко.
MrWonderful

@ AmarthGûl - Як можна отримати результати з циклу for для сценарію всередині <решта коду> для обробки? Можливо, у списку? А може, дикту? Якщо так, то застосовується та ж логіка. Я не розумію, як змінне введення може мати будь-який ефект у будь-якому вигляді розумно розробленого коду, де обробка порожнього списку була б поганою ідеєю.
MrWonderful

Трохи старий, але якщо ви просто перевіряли, чи список порожній, для не порожнього списку ваш код повторює процес знову і знову, коли ОП просто шукає перевірку. Просто уявіть гірший сценарій цього коду, коли n наближається до нескінченності ....
DJK

7
@DJK - Ні, я думаю, ти все ще не вистачає цього. Імовірно, ви хочете щось зробити зі списком, якщо у вас є такий. Що б ти зробив інакше, якби він був порожнім? Повернутися рано? Що робити, якщо він не порожній? обробляти? Справа в тому, що вам, мабуть , не потрібно перевіряти порожній список, просто перебирайте його та робіть все, що ви збиралися робити з елементами. Якщо елементів немає, ви пропадаєте. Якщо є елементи, ви обробляєте їх так, як вам потрібно. Справа НЕ в тому, щоб використовувати приклад ДЛЯ порожньої перевірки, а краще НЕ перевірити зовсім, просто обробити список.
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

перший тест - відповідь на відповідь @ Майка вище. Третій рядок також можна замінити на:

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

якщо ви хочете приймати лише екземпляри певних типів (та їх підтипів) або з:

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

Ви можете піти без чіткої перевірки типу, але лише якщо навколишній контекст вже запевняє вас, що aце значення типів, з якими ви готові обробляти, або якщо ви впевнені, що типи, з якими ви не готові оброблятись, збираються підвищувати помилки (наприклад, TypeErrorякщо ви посилаєтесь lenна значення, для якого воно не визначене), яке ви готові обробити. Взагалі, «пітонічні» умовності, здається, йдуть цим останнім шляхом. Стисніть її, як качку, і дайте їй підняти DuckError, якщо він не знає, як трясти. Ви все ще повинні подумати про те, які саме припущення ви робите, та чи справді справи, з якими ви не готові керуватися належним чином, помиляються в потрібних місцях. Масиви Numpy - хороший приклад, коли просто сліпо покладаються на нихlen або булева клавіша може не робити саме те, що ви очікуєте.


3
Досить рідко трапляється вичерпний список із 6 типів, які ви бажаєте прийняти та не бути гнучкими для будь-яких інших типів. Коли вам потрібна така річ, ви, мабуть, хочете ABC. У цьому випадку, ймовірно, це буде один із stdlib ABC, наприклад, collections.abc.Sizedабо collections.abc.Sequence, але це може бути той, який ви пишете самостійно та register(list)далі. Якщо у вас дійсно є код, де важливо відрізнити порожній від інших фальси, а також відрізнити списки та кортежі від будь-яких інших послідовностей, то це правильно - але я не вірю, що у вас такий код.
abarnert

13
Причина людям цього не подобається в тому, що в більшості випадків це абсолютно неестерично. Python - мова, що набирає качок, і цей рівень захисного кодування активно перешкоджає цьому. Ідея системи типу Python полягає в тому, щоб все працювало до тих пір, поки об’єкт передається у функції так, як йому потрібно. Роблячи явні перевірки типу, ви змушуєте абонента використовувати конкретні типи, що суперечить самій зерна мови. Хоча час від часу такі речі необхідні (за винятком рядків, що трактуються як послідовності), такі випадки рідкісні і майже завжди найкращі як чорні списки.
Гарет Летті

1
Якщо ви дійсно хочете перевірити, чи є значення саме таким, []а не чимось хибним іншим типом, тоді, безумовно if a == []:, вимагається, а не обмірковуватися із суттєвістю.
РемкоГерліх

2
==Хоча є кілька автоматичних примусів . У верхній частині голови я не можу визначити жодного []. [] == ()наприклад, повертає False. Але, наприклад, frozenset()==set()повертається True. Тому варто хоча б подумати про те, чи можна примушувати примушувати [](чи навпаки) якийсь небажаний тип a == [].
сумнівним

@RemcoGerlich - isin substance () все ще є переважним на відміну від побудови порожнього списку для порівняння. Крім того, як вказував інший, оператор рівності може викликати неявну конверсію деяких типів, що може бути небажаним. Немає ніяких причин коли-небудь кодувати "a == []", і цей код обов'язково буде позначений як дефект у будь-якому огляді коду, в якому я брав участь. Використання відповідного інструменту, передбаченого мовою, не слід вважати "глухим про , ", але" хороша техніка програмування ".
MrWonderful

29

З документації щодо перевірки цінності на істинність:

Всі значення, крім зазначених тут, враховуються True

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

Як видно, порожній список []є хибним , тому те, що було б зроблено для булевого значення, звучить найбільш ефективно:

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

@DJ_Stuffy_K стверджують, що в одиничному тестуванні порожній список? Просто використовуйте assert(not myList). Якщо ви також хочете стверджувати, що об'єкт є list, ви можете використовувати assertIsInstance().
Snađошƒаӽ

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")

20

Я віддаю перевагу наступному:

if a == []:
   print "The list is empty."

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")

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-ness, не потрібно цього робити.

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

8

Дано багато відповідей, і багато з них досить непогані. Я просто хотів додати, що чек

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 '...'
Свен Крюгер

4
@ SvenKrüger nope. Оператор 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 in l) Істинно для порожнього списку
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не якийсь контейнер. (Бути ітерабельним також дозволяє ітераторів, які не можна корисно перевірити на порожнечу.)
Девіс Херінг


4

Від python3 і далі ви можете використовувати

a == []

щоб перевірити, чи список порожній

EDIT: Це також працює з python2.7.

Я не впевнений, чому так багато складних відповідей. Це досить чітко і прямо


1
будь ласка, дайте більше пояснень щодо того, як це працює, не пишете "якщо"?
Ганешдешмух

3
Це не пітонічний і не повний приклад. Крім того, він створює порожній список кожного разу, коли він стикається. Не робіть цього.
MrWonderful

@MrWonderful не щоразу створює порожній список. Він просто перевіряє, чи наявний список aпорожній чи ні.
Tessaracter

@MrWonderful Я не розумію, що це робитьpythonic
Tessaracter

@ganeshdeshmukh, якщо ви a==[]його використовуєте, буде надруковано true на терміналі python, якщо a порожній. В іншому випадку буде надруковано False. Ви можете використовувати це всередині умови 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змінну return . Вибір за вами. Я пишу обидва, щоб ви могли вибрати між ними.
Vineet Jain


1

Значення істинності порожнього списку становить Falseтоді, коли для не порожнього списку воно є True.


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"

Сподіваюсь, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.