ordinare - vettori in python




Come posso verificare se una lista è vuota? (20)

Ad esempio, se ha superato quanto segue:

a = []

Come faccio a verificare se a è vuoto?


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'istruzione if o while ). Verificherà False se è vuoto e True contrario. 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.

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

Per impostazione predefinita, un oggetto è considerato true a meno che la sua classe non definisca un __bool__() che restituisce False o un __len__() che restituisce zero, quando 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 raccolte vuote: '' , () , [] , {} , set() , range(0)

E la documentazione del datamodel:

object.__bool__(self)

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

e

object.__len__(self)

Chiamato per implementare la funzione built-in len() . Dovrebbe restituire la lunghezza dell'oggetto, un numero intero> = 0. Inoltre, un oggetto che non definisce un __bool__() e il cui metodo __len__() 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

Vediamo che il controllo della lunghezza con la funzione built len rispetto a 0 o il controllo su una lista vuota è molto meno performante rispetto all'uso della sintassi incorporata della lingua come documentato.

Perché?

Per la len(a) == 0 controlla:

Il primo Python deve controllare i globali per vedere se len è in ombra.

Quindi deve chiamare la funzione, caricare 0 ed eseguire 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 compilare un elenco non necessario e poi, di nuovo, 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 campo ob_size . 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 della macro PyObject_VAR_HEAD .

Dalla sorgente c in Include/listobject.h :

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

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.


Perché controllare?

Nessuno sembra aver affrontato la necessità di 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 modo più plateale è non controllare affatto, ma piuttosto elaborare semplicemente la lista. 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 a , mentre non richiede un controllo specifico per il vuoto. Se a è 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.


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 sia disposto a gestire casi in cui a è, ad esempio, False , è necessario un test più restrittivo che 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à che a è un valore dei tipi che sei preparato a gestire, o se sei sicuro che i tipi che non sei preparato a gestire siano andando a generare errori (ad esempio, un errore 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 quali supposizioni di tipo stai facendo, però, e se i casi che non sei pronto a gestire correttamente andranno in errore nei posti giusti. Gli array di Numpy sono un buon esempio in cui affidarsi ciecamente a len o al typecast booleano potrebbe non fare esattamente quello che ti aspetti.


Basta usare is_empty () o fare una funzione del tipo: -

def is_empty(any_structure):
    if any_structure:
        print('Structure is not empty.')
        return True
    else:
        print('Structure is empty.')
        return False  

Può essere utilizzato per qualsiasi data_structure come un elenco, tuple, dizionario e molti altri. Con questi, puoi chiamarlo molte volte usando solo is_empty(any_structure) .


Dalla documentation sui test del valore di verità:

Tutti i valori diversi da quelli elencati qui sono considerati True

  • None
  • False
  • zero di qualsiasi tipo numerico, ad esempio 0 , 0.0 , 0j .
  • qualsiasi sequenza vuota, ad esempio, '' , () , [] .
  • qualsiasi mappatura vuota, ad esempio, {} .
  • istanze di classi definite dall'utente, se la classe definisce un __bool__() o __len__() , quando quel metodo restituisce lo zero intero o il valore bool False .

Come si può vedere, la lista vuota [] è falsa , quindi fare ciò che sarebbe fatto per un valore booleano sembra più efficiente:

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

Ecco alcuni modi per verificare se una lista è vuota:

a = [] #the list

1) La semplice maniera pitonica:

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

In Python, i contenitori vuoti come liste, tuple, set, dicts, variabili ecc sono visti come False . Si potrebbe semplicemente considerare la lista come un predicato ( restituendo un valore booleano ). E un valore True indicherebbe che non è vuoto.

2) Un modo molto esplicito: usare len() per trovare la lunghezza e verificare se è uguale a 0 :

if len(a) == 0:
    print("a is empty")

3) o confrontandolo con una lista vuota anonima:

if a == []:
    print("a is empty")

4) Un altro modo ancora stupido di fare è usare exception e iter() :

try:
    next(iter(a))
    # list has elements
except StopIteration:
    print("Error: a is empty")

Ho visto il seguente come preferito:

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

Il modo pitone per farlo è dalla guida di stile PEP 8 (dove significa "raccomandato" e No significa "non raccomandato"):

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

Lo preferisco esplicitamente:

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

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


Molte risposte sono state date, e molte sono abbastanza buone. Volevo solo aggiungere quell'assegno

not a

passerà anche per None e altri tipi di strutture vuote. Se vuoi veramente controllare una lista vuota, puoi farlo:

if isinstance(a, list) and len(a)==0:
    print("Received an empty list")

Puoi anche provare a usare bool () come questo

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

Adoro in questo modo che l'elenco di controllo sia vuoto o no.

Molto utile e utile.


Python è molto uniforme sul trattamento del vuoto. Dato quanto segue:

a = []

.
.
.

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

Basta controllare la lista a con un'istruzione "if" per vedere se è vuota. Da quello che ho letto e insegnato, questo è il modo "Pythonico" per vedere se una lista o tupla è vuota.


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

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

@Daren Thomas

EDIT: Un altro punto contro il test della lista vuota come False: per quanto riguarda il polimorfismo? Non dovresti dipendere da una lista che è una lista. Dovrebbe semplicemente ciarlare come un'anatra - come farai a smettere di ciondolare la tua collezione di anatre "Falso" quando non ha elementi?

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



Collection.Any () restituisce sempre false se l'elenco è vuoto


Guarda il seguente codice eseguito sul terminale interattivo Python.

>>> a = []
>>> if a:
...     print "List is not empty";
... else:
...     print "List is empty"
... 
List is empty
>>> 
>>> a = [1, 4, 9]
>>> if a:
...     print "List is not empty";
... else:
...     print "List is empty"
... 
List is not empty
>>> 

Se si desidera verificare se l'elenco è vuoto;

l = []
if l:
    # do your stuff.

Se si desidera controllare il tempo tutti i valori nella lista sono vuoti.

l = ["", False, 0, '', [], {}, ()]
if all(bool(x) for x in l):
    # do your stuff.

Tuttavia questo sarà Vero per la lista vuota.

def empty_list(lst):
    if len(lst) ==0:
        return false
    else:
        return all(bool(x) for x in l)

Ora puoi usare:

if empty_list(lst):
    # do your stuff.

Un approccio non ufficiale:

 a = []
 try:
  print(a[-1])
 except IndexError:
  print("List 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])

A volte è bene testare separatamente per None e per vuoto, poiché si tratta di due stati diversi. Il codice sopra produce il seguente output:

list is None 
list is empty 
list has 3 elements

Anche se non vale niente che None sia falsato. Quindi se non vuoi separare il test per None -ness, non devi farlo.

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

produce previsto

list is empty
list is empty
list has 3 elements

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

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





is-empty