Domanda Come posso verificare se una lista è vuota?


Ad esempio, se ha superato quanto segue:

a = []

Come controllo per vedere se a è vuoto?


2717
2017-09-10 06:20


origine


risposte:


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

Usare l'implicita booleana della lista vuota è piuttosto pitonico.


3885
2017-09-10 06:28



Il modo pitonico per farlo è dal Guida allo stile PEP 8 (dove  significa "consigliato" e No significa "non raccomandato"):

Per le sequenze (stringhe, elenchi, tuple), usa il fatto che le sequenze vuote sono false.   

Sì: if not seq:
     if seq:

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

862
2017-09-10 10:33



Lo preferisco esplicitamente:

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

In questo modo è chiaro al 100% li è una sequenza (lista) e vogliamo testarne le dimensioni. Il mio problema con if not li: ... è che dà la falsa impressione che li è una variabile booleana.


517
2017-09-05 00:30



Altre persone sembrano generalizzare la domanda al di là delle sole liste, quindi ho pensato di aggiungere un avvertimento per un diverso tipo di sequenza che molte persone potrebbero usare, specialmente perché questo è il primo hit di google per "python test empty array" .

Altri metodi non funzionano con gli array numpy

Devi stare attento con gli array numpy, perché altri metodi funzionano bene lists o altri contenitori standard falliscono per gli array numpy. Spiego perché qui sotto, ma in breve, il metodo preferito è da usare size.

Il modo "pythonic" non funziona: parte 1

Il modo "pythonic" fallisce con gli array numpy perché numpy prova a lanciare l'array su un array bools, e if x cerca di valutare tutti quelli bools in una sola volta per una sorta di valore di verità aggregato. Ma questo non ha alcun senso, quindi ottieni un 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()

Il modo "pythonic" non funziona: parte 2

Ma almeno il caso sopra ti dice che ha fallito. Se ti capita di avere una matrice numpy con esattamente un elemento, il if la dichiarazione funzionerà "nel senso che non si ottiene un errore. Tuttavia, se quello è un elemento 0 (o 0.0, o false, ...), il if la dichiarazione non verrà eseguita correttamente false:

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

Ma chiaramente x esiste e non è vuoto! Questo risultato non è quello che volevi.

utilizzando len può dare risultati inaspettati

Per esempio,

len( numpy.zeros((1,0)) )

restituisce 1, anche se l'array ha zero elementi.

Il modo numpythonic

Come spiegato nel FAQ di scipy, il metodo corretto in tutti i casi in cui sai che devi usare un array 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

Se non sei sicuro se potrebbe essere un list, una matrice numpy o qualcos'altro, è possibile combinare questo approccio con la risposta @dubiousjim dà per assicurarsi che venga usato il test giusto per ciascun tipo. Non molto "pythonic", ma risulta che Numpy intenzionalmente spezzò la pitonicità almeno in questo senso.

Se devi fare qualcosa di più che controllare se l'input è vuoto e stai usando altre funzioni di numpy come l'indicizzazione o le operazioni matematiche, probabilmente è più efficiente (e sicuramente più comune) forzare l'input essere una matrice numpy. Ci sono alcune funzioni utili per farlo rapidamente, soprattutto numpy.asarray. Questo prende il tuo input, non fa nulla se è già un array, o avvolge il tuo input in un array se è un elenco, una tupla, ecc. E, facoltativamente, lo converte nel tuo scelto dtype. Quindi è molto veloce ogni volta che può essere, e garantisce che si possa solo assumere che l'input sia una matrice numpy. Solitamente usiamo anche lo stesso nome, dato che la conversione in un array non tornerà al di fuori del corrente scopo:

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

Questo renderà il x.size controlla il lavoro in tutti i casi che vedo in questa pagina.


208
2018-02-21 16:48



Una lista vuota è di per sé considerata falsa in veri test di valore (vedi documentazione di Python):

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

@Daren Thomas

EDIT: un altro punto contro i test   la lista vuota come False: che dire   polimorfismo? Non dovresti dipendere da   una lista è una lista. Dovrebbe solo   ciarlatano come un'anatra - come stai andando   per ottenere il tuo duckCollection a ciarlare   '' Falso '' quando non ha elementi?

Il tuo duckCollection dovrebbe implementare __nonzero__ o __len__ quindi if a: funzionerà senza problemi.


103
2017-09-10 06:31



La risposta (accettata) di Patrick è giusto: if not a: è il modo giusto per farlo La risposta di Harley Holcombe è giusto che questo sia nella guida di stile PEP 8. Ma ciò che nessuna delle risposte spiega è perché sia ​​una buona idea seguire l'idioma, anche se personalmente trovi che non è abbastanza esplicito o che confonde gli utenti di Ruby o qualsiasi altra cosa.

Il codice Python e la comunità Python hanno idiomi molto forti. Seguire questi idiomi rende il tuo codice più facile da leggere per chiunque abbia esperienza in Python. E quando si violano quegli idiomi, questo è un segnale forte.

È vero if not a: non distingue le liste vuote da None, o numerica 0, o tuple vuote, o vuoti tipi di raccolta creati dall'utente, o vuoti tipi non-creati dall'insieme creati dall'utente, o array NumPy a elemento singolo che agisce come scalari con valori falsi, ecc. E a volte è importante essere esplicito al riguardo. E in tal caso, lo sai che cosa vuoi essere esplicito, quindi puoi testare esattamente questo. Per esempio, if not a and a is not None: significa "tutto falso tranne Nessuno", mentre if len(a) != 0: significa "solo sequenze vuote - e qualsiasi cosa oltre a una sequenza è un errore qui", e così via. Oltre a testare esattamente ciò che si desidera testare, questo segnala anche al lettore che questo test è importante.

Ma quando non hai nulla di cui essere esplicito, qualcosa di diverso da if not a: è fuorviante il lettore. Stai segnalando qualcosa di importante quando non lo è. (Puoi anche rendere il codice meno flessibile, o più lento, o altro, ma è meno importante.) E se tu abitualmente ingannare il lettore in questo modo, poi quando tu fare devi fare una distinzione, passerà inosservata perché hai "pianto lupo" su tutto il tuo codice.


81
2017-12-03 02:21



Il modo migliore per verificare se una lista è vuota

Ad esempio, se ha superato quanto segue:

a = []

Come faccio a verificare se un è vuoto?

Risposta breve:

Posiziona la lista in un contesto booleano (ad esempio, con un if o whiledichiarazione). Metterà alla prova False se è vuoto, e True altrimenti. Per esempio:

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

Ricorso all'autorità

PEP 8, la guida in stile Python ufficiale per il codice Python nella libreria standard di Python, asserisce:

Per le sequenze (stringhe, elenchi, tuple), usa il fatto che le sequenze vuote sono false.

Yes: if not seq:
     if seq:

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

Dovremmo aspettarci che il codice della libreria standard sia il più performante e il più corretto possibile. Ma perché è così, e perché abbiamo bisogno di questa guida?

Spiegazione

Vedo spesso codice come questo da programmatori esperti nuovi in ​​Python:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

E gli utenti di lingue pigre potrebbero essere tentati di farlo:

if a == []:                         # Don't do this!
    print('a is an empty list')

Questi sono corretti nelle loro rispettive altre lingue. E questo è anche semanticamente corretto in Python.

Ma lo consideriamo non-Pythonic perché Python supporta questa semantica direttamente nell'interfaccia dell'oggetto lista tramite la coercizione booleana.

Dal docs (e si noti specificamente l'inclusione della lista vuota, []):

Di default, un oggetto è considerato vero a meno che la sua classe non lo definisca   o a __bool__() metodo che restituisce False o a __len__() metodo   che restituisce zero, quando viene chiamato con l'oggetto. Ecco la maggior parte degli oggetti incorporati considerati falsi:

  • costanti definite come false: None e False.
  • zero di qualsiasi tipo numerico: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • sequenze e collezioni vuote: '', (), [], {}, set(), range(0)

E la documentazione del datamodel:

object.__bool__(self)

Chiamato per implementare il test del valore di verità e l'operazione integrata bool(); dovrebbe tornare False o True. Quando questo metodo non è definito,    __len__() viene chiamato, se è definito, e l'oggetto è considerato vero se il suo risultato è diverso da zero. Se una classe non definisce né __len__()   né __bool__(), tutte le sue istanze sono considerate vere.

e

object.__len__(self)

Chiamato per implementare la funzione integrata len(). Dovrebbe restituire la lunghezza dell'oggetto, un numero intero> = 0. Inoltre, un oggetto che non definisce a __bool__() metodo e di chi __len__() il metodo restituisce zero è considerato falso in un contesto booleano.

Quindi, invece di questo:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

o questo:

if a == []:                     # Don't do this!
    print('a is an empty list')

Fai questo:

if not a:
    print('a is an empty list')

Fare ciò che Pythonic di solito paga in termini di prestazioni:

Paga? (Nota che meno tempo per eseguire un'operazione equivalente è meglio :)

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

Per la scala, ecco il costo di chiamare la funzione e costruire e restituire una lista vuota, che potresti sottrarre dai costi dei controlli di vuoto usati sopra:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

Lo vediamo o controllando la lunghezza con la funzione integrata len rispetto a 0  o è il controllo su una lista vuota tanto meno performante rispetto all'uso della sintassi integrata della lingua come documentato.

Perché?

Per il len(a) == 0 dai un'occhiata:

Il primo Python deve controllare i globali per vedere se len è ombreggiato

Quindi deve chiamare la funzione, caricare 0e fai il confronto di uguaglianza in Python (invece che con 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

E per il [] == []deve costruire una lista non necessaria e poi, ancora, eseguire l'operazione di confronto nella macchina virtuale di Python (al contrario di C)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

Il modo "Python" è un controllo molto più semplice e veloce poiché la lunghezza dell'elenco è memorizzata nella cache nell'intestazione dell'istanza dell'oggetto:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

Prove dalla fonte C e documentazione

PyVarObject

Questa è un'estensione di PyObject che aggiunge il ob_size campo. Questo è usato solo per oggetti che hanno qualche nozione di lunghezza. Questo tipo non appare spesso nell'API Python / C. Corrisponde ai campi definiti dall'espansione del PyObject_VAR_HEAD macro.

Dalla sorgente c in Includere / 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

Mi sono divertito a fare ricerche su questo e trascorro molto tempo a curare le mie risposte. Se pensi che sto lasciando qualcosa fuori, per favore fatemelo sapere in un commento.


80
2017-08-20 03:50



Ho visto il seguente come preferito:

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

62
2017-09-10 06:28



Perché controllare?

Nessuno sembra aver affrontato il tuo problema bisogno per testare la lista in primo luogo. Poiché non hai fornito alcun contesto aggiuntivo, posso immaginare che potresti non aver bisogno di fare questo controllo in primo luogo, ma non hai familiarità con l'elaborazione delle liste in Python.

Direi che il più pythonic il modo è di non controllare affatto, ma piuttosto di elaborare l'elenco. In questo modo farà la cosa giusta, vuota o completa.

a = []

for item in a:
    <do something with item>

<rest of code>

Questo ha il vantaggio di gestire qualsiasi contenuto di un, pur non richiedendo un controllo specifico per il vuoto. Se un è vuoto, il blocco dipendente non verrà eseguito e l'interprete passerà alla riga successiva.

Se in effetti è necessario controllare la presenza della matrice per il vuoto, le altre risposte sono sufficienti.


50
2017-10-06 19:25



len() è un'operazione O (1) per gli elenchi, le stringhe, i dadi e gli insiemi di Python. Python tiene traccia internamente del numero di elementi in questi contenitori.

JavaScript ha una nozione simile di verità / falsità.


44
2017-09-15 05:50



Avevo scritto:

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

che è stato votato -1. Non sono sicuro che sia perché i lettori si sono opposti alla strategia o hanno pensato che la risposta non fosse utile come presentata. Farò finta che fosse il secondo, dal momento che --- qualunque cosa contenga "pythonic" --- questa è la strategia corretta. A meno che tu non abbia già escluso, o sei pronto a gestire casi in cui a è, per esempio, False, hai bisogno di un test più restrittivo del solo if not a:. Potresti usare qualcosa come questo:

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

il primo test è in risposta alla risposta di @ Mike, sopra. La terza riga potrebbe anche essere sostituita con:

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

se vuoi solo accettare istanze di tipi particolari (e i loro sottotipi), o con:

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

Puoi andare via senza il controllo esplicito del tipo, ma solo se il contesto circostante ti assicura già questo a è un valore dei tipi che sei preparato a gestire, o se sei sicuro che i tipi che non sei preparato a gestire aumenteranno gli errori (ad es. TypeError se chiami len su un valore per il quale non è definito) che sei pronto a gestire. In generale, le convenzioni "pitoniche" sembrano andare fino in fondo. Stringilo come un'anatra e lascia che rilanci DuckError se non sa come ciarlare. Devi ancora pensare a proposito di quali supposizioni di tipo stai facendo, però, e se i casi che non sei pronto a gestire in modo corretto vadano per errore nei posti giusti. Gli array di Numpy sono un buon esempio in cui ci affidiamo solo ciecamente len o il typecast booleano potrebbe non fare esattamente quello che ti aspetti.


28
2018-05-31 14:35