Come posso ottenere il numero di elementi in un elenco?


1938

Considera quanto segue:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

# FAKE METHOD:
items.amount()  # Should return 3

Come posso ottenere il numero di elementi nell'elenco items?


23
Ovviamente stai chiedendo il numero di elementi nell'elenco. Se un ricercatore viene qui alla ricerca della dimensione dell'oggetto in memoria, questa è la vera domanda e le risposte che sta cercando: come posso determinare la dimensione di un oggetto in Python?
Aaron Hall

Risposte:


2640

La len()funzione può essere utilizzata con diversi tipi in Python - sia tipi incorporati che tipi di libreria. Per esempio:

>>> len([1,2,3])
3

La documentazione ufficiale 2.x è qui: La documentazione ufficiale 3.x è qui:len()
len()


239

Come ottenere le dimensioni di un elenco?

Per trovare le dimensioni di un elenco, utilizzare la funzione built-in, len:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

E adesso:

len(items)

ritorna 3.

Spiegazione

Tutto in Python è un oggetto, compresi gli elenchi. Tutti gli oggetti hanno un'intestazione di qualche tipo nell'implementazione C.

Gli elenchi e altri oggetti incorporati simili con una "dimensione" in Python, in particolare, hanno un attributo chiamato ob_size, in cui viene memorizzato nella cache il numero di elementi nell'oggetto. Quindi controllare il numero di oggetti in un elenco è molto veloce.

Ma se stai controllando se la dimensione dell'elenco è zero o no, non usare len- invece, metti l'elenco in un contesto booleano - trattato come False se vuoto, True altrimenti .

Dai documenti

len(s)

Restituisce la lunghezza (il numero di elementi) di un oggetto. L'argomento può essere una sequenza (come una stringa, byte, tupla, elenco o intervallo) o una raccolta (come un dizionario, un insieme o un insieme congelato).

lenè implementato con __len__, dai documenti del modello dati :

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 un metodo __nonzero__()[in Python 2 o __bool__()in Python 3] e il cui __len__()metodo restituisce zero è considerato falso in un contesto booleano.

E possiamo anche vedere che __len__è un metodo di elenchi:

items.__len__()

ritorna 3.

Tipi incorporati di cui è possibile ottenere la len(lunghezza)

E infatti vediamo che possiamo ottenere queste informazioni per tutti i tipi descritti:

>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list, 
                                            xrange, dict, set, frozenset))
True

Non utilizzare lenper verificare un elenco vuoto o non vuoto

Per testare una lunghezza specifica, ovviamente, è sufficiente verificare l'uguaglianza:

if len(items) == required_length:
    ...

Ma c'è un caso speciale per i test per un elenco di lunghezza zero o l'inverso. In tal caso, non testare l'uguaglianza.

Inoltre, non fare:

if len(items): 
    ...

Invece, fai semplicemente:

if items:     # Then we have some items, not empty!
    ...

o

if not items: # Then we have an empty list!
    ...

Mi spiego perché qui , ma insomma, if itemso if not itemssia più leggibile e più performante.


75

Mentre questo potrebbe non essere utile a causa del fatto che avrebbe molto più senso come funzionalità "out of the box", un trucco abbastanza semplice sarebbe quello di costruire una classe con una lengthproprietà:

class slist(list):
    @property
    def length(self):
        return len(self)

Puoi usarlo così:

>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In sostanza, è esattamente identico a un oggetto elenco, con l'ulteriore vantaggio di avere una lengthproprietà compatibile con OOP .

Come sempre, il tuo chilometraggio può variare.


19
solo così sai, puoi semplicemente fare length = property(len)e saltare la funzione wrapper a una riga e conservare la documentazione / introspezione lencon la tua proprietà.
Tadhg McDonald-Jensen,

17

Inoltre lenpuoi anche usare operator.length_hint(richiede Python 3.4+). Per un normale listentrambi sono equivalenti, ma length_hintrende possibile ottenere la lunghezza di un elenco-iteratore, che potrebbe essere utile in determinate circostanze:

>>> from operator import length_hint
>>> l = ["apple", "orange", "banana"]
>>> len(l)
3
>>> length_hint(l)
3

>>> list_iterator = iter(l)
>>> len(list_iterator)
TypeError: object of type 'list_iterator' has no len()
>>> length_hint(list_iterator)
3

Ma length_hintè per definizione solo un "suggerimento", quindi il più delle volte lenè meglio.

Ho visto diverse risposte che suggeriscono l'accesso __len__. Questo va bene quando si tratta di classi integrate come list, ma potrebbe portare a problemi con le classi personalizzate, perché len(e length_hint) implementare alcuni controlli di sicurezza. Ad esempio, entrambi non consentono lunghezze o lunghezze negative che superano un determinato valore (il sys.maxsizevalore). Quindi è sempre più sicuro usare la lenfunzione invece del __len__metodo!


8

Rispondere alla tua domanda come gli esempi forniti anche in precedenza:

items = []
items.append("apple")
items.append("orange")
items.append("banana")

print items.__len__()

15
In Python, i nomi che iniziano con i trattini bassi sono metodi semanticamente non pubblici e non devono essere utilizzati dagli utenti.
Aaron Hall

2
1 __foo__.: questa è solo una convenzione, un modo per il sistema Python di usare nomi che non entreranno in conflitto con i nomi degli utenti. 2 _foo.: questa è solo una convenzione, un modo per il programmatore di indicare che la variabile è privata (qualunque cosa ciò significhi in Python). 3 __foo.: questo ha un significato reale: l'interprete sostituisce questo nome con _classname__fooun modo per assicurarsi che il nome non si sovrapponga a un nome simile in un'altra classe. * Nessun'altra forma di trattini bassi ha significato nel mondo Python. * Non c'è alcuna differenza tra classe, variabile, globale, ecc. In queste convenzioni.
Shai Alon,

4
Queste domande e risposte spiegano perché non dovresti usare i metodi speciali direttamente come utente: stackoverflow.com/q/40272161/541136
Aaron Hall

@AaronHall ma per la funzione len è quasi lo stesso. Potrebbe essere più veloce per variabili molto grandi. Tuttavia, ottengo il tuo punto e dovremmo usare len (obj) e non obj .__ len __ ().
Shai Alon,

7

E per completezza (principalmente educativa), è possibile senza usare la len()funzione. Non lo perdonerei come una buona opzione NON PROGRAMMARE COME QUESTO IN PYTHON , ma serve a uno scopo di apprendimento degli algoritmi.

def count(list):
    item_count = 0
    for item in list[:]:
        item_count += 1
    return item_count

count([1,2,3,4,5])

(Il colon in list[:]è implicito ed è quindi anche facoltativo.)

La lezione qui per i nuovi programmatori è: non è possibile ottenere il numero di elementi in un elenco senza contarli ad un certo punto. La domanda diventa: quando è il momento giusto per contarli? Ad esempio, un codice ad alte prestazioni come la chiamata del sistema connect per socket (scritto in C) connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);, non calcola la lunghezza degli elementi (attribuendo tale responsabilità al codice chiamante). Notare che la lunghezza dell'indirizzo viene passata per salvare il passaggio del conteggio della lunghezza prima? Un'altra opzione: dal punto di vista computazionale, potrebbe avere senso tenere traccia del numero di elementi mentre li aggiungi all'interno dell'oggetto che passi. Ricorda che questo occupa più spazio nella memoria. Vedi la risposta di Naftuli Kay .

Esempio di monitoraggio della lunghezza per migliorare le prestazioni occupando più spazio in memoria. Nota che non utilizzo mai la funzione len () perché viene tracciata la lunghezza:

class MyList(object):
    def __init__(self):
        self._data = []
        self.length = 0 # length tracker that takes up memory but makes length op O(1) time


        # the implicit iterator in a list class
    def __iter__(self):
        for elem in self._data:
            yield elem

    def add(self, elem):
        self._data.append(elem)
        self.length += 1

    def remove(self, elem):
        self._data.remove(elem)
        self.length -= 1

mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
print(mylist.length) # 3
mylist.remove(3)
print(mylist.length) # 2

Perché for item in list[:]:? Perché no for item in list:? Inoltre, userei += 1per incrementare.
Nonna dolorante,

@GrannyAching Ho menzionato esplicitamente i due punti opzionali (identificatore di intervallo). Ho lasciato l'identificatore di portata lì per scopi educativi, è utile sapere che è implicito. Viene dedotto anche un tipo di elenco [], come suggerisci, equivalente al mio codice. L'operatore di incremento equivale anche ad aggiungere 1 a una variabile esistente, ma più breve in tutti i casi. Quindi concordo sul fatto che dovrebbe essere usato se questo è il tuo ragionamento. Questo codice non dovrebbe essere messo in produzione da nessuna parte, comunque (tranne quando si impara a programmare).
Jonathan Komar,

0

In termini di come len()funziona effettivamente, questa è la sua implementazione in C :

static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
    Py_ssize_t res;

    res = PyObject_Size(obj);
    if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }
    return PyLong_FromSsize_t(res);
}

Py_ssize_tè la lunghezza massima che l'oggetto può avere. PyObject_Size()è una funzione che restituisce la dimensione di un oggetto. Se non è in grado di determinare la dimensione di un oggetto, restituisce -1. In tal caso, questo blocco di codice verrà eseguito:

if (res < 0) {
        assert(PyErr_Occurred());
        return NULL;
    }

E di conseguenza viene sollevata un'eccezione. Altrimenti, questo blocco di codice verrà eseguito:

return PyLong_FromSsize_t(res);

resche è un Cnumero intero, viene convertito in un pitone longe restituito. Tutti i numeri interi di Python sono memorizzati come longsda Python 3.


3
Perché è importante conoscere o conoscere l'implementazione C?
cs95,

Poiché questa domanda non è specifica per CPython, questa risposta potrebbe essere fuorviante. PyPy, IronPython, ... possono implementarlo diversamente.
MSeifert,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.