Wie erhalte ich die Anzahl der Elemente in einer Liste?

1937

Folgendes berücksichtigen:

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

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

Wie erhalte ich die Anzahl der Elemente in der Liste items?

y2k
quelle
23
Sie fragen offensichtlich nach der Anzahl der Elemente in der Liste. Wenn ein Sucher hierher kommt und nach der Größe des Objekts im Speicher sucht, ist dies die eigentliche Frage und Antwort, nach der er sucht: Wie bestimme ich die Größe eines Objekts in Python?
Aaron Hall

Antworten:

2640

Die len()Funktion kann in Python mit verschiedenen Typen verwendet werden - sowohl mit integrierten Typen als auch mit Bibliothekstypen. Zum Beispiel:

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

Die offizielle 2.x-Dokumentation finden Sie hier: Die offizielle 3.x-Dokumentation finden Sie hier:len()
len()

Gnud
quelle
239

Wie erhalte ich die Größe einer Liste?

Verwenden Sie die integrierte Funktion, um die Größe einer Liste zu ermitteln len:

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

Und nun:

len(items)

gibt 3 zurück.

Erläuterung

Alles in Python ist ein Objekt, einschließlich Listen. Alle Objekte haben in der C-Implementierung eine Art Header.

Insbesondere Listen und andere ähnliche integrierte Objekte mit einer "Größe" in Python haben ein Attribut namens ob_size, bei dem die Anzahl der Elemente im Objekt zwischengespeichert wird. Das Überprüfen der Anzahl der Objekte in einer Liste ist daher sehr schnell.

Wenn Sie jedoch überprüfen, ob die Listengröße Null ist oder nicht, verwenden Sie sie nicht len. Setzen Sie die Liste stattdessen in einen booleschen Kontext. Sie wird als falsch behandelt, wenn sie leer ist, andernfalls als wahr .

Aus den Dokumenten

len(s)

Gibt die Länge (die Anzahl der Elemente) eines Objekts zurück. Das Argument kann eine Sequenz (z. B. eine Zeichenfolge, Bytes, ein Tupel, eine Liste oder ein Bereich) oder eine Sammlung (z. B. ein Wörterbuch, eine Menge oder eine eingefrorene Menge) sein.

lenimplementiert mit __len__, aus dem Datenmodell docs :

object.__len__(self)

Wird aufgerufen, um die integrierte Funktion zu implementieren len(). Sollte die Länge des Objekts zurückgeben, eine Ganzzahl> = 0. Auch ein Objekt, das keine __nonzero__()[in Python 2 oder __bool__()in Python 3] -Methode definiert und dessen __len__()Methode Null zurückgibt, wird in einem booleschen Kontext als falsch betrachtet.

Und wir können auch sehen, dass dies __len__eine Methode von Listen ist:

items.__len__()

gibt 3 zurück.

Eingebaute Typen, deren lenLänge Sie erhalten können

Und tatsächlich sehen wir, dass wir diese Informationen für alle beschriebenen Typen erhalten können:

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

Nicht lenzum Testen auf eine leere oder nicht leere Liste verwenden

Um auf eine bestimmte Länge zu testen, testen Sie natürlich einfach die Gleichheit:

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

Es gibt jedoch einen Sonderfall für das Testen auf eine Liste mit der Länge Null oder die Umkehrung. In diesem Fall nicht auf Gleichheit prüfen.

Tun Sie auch nicht:

if len(items): 
    ...

Tun Sie stattdessen einfach:

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

oder

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

Ich erkläre warum hier aber kurz if itemsoder if not itemsist sowohl lesbarer als auch performanter.

Aaron Hall
quelle
75

Dies ist möglicherweise nicht sinnvoll, da es als "out of the box" -Funktionalität viel sinnvoller wäre. Ein ziemlich einfacher Hack wäre jedoch, eine Klasse mit einer lengthEigenschaft zu erstellen :

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

Sie können es so verwenden:

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

Im Wesentlichen ist es genau identisch mit einem Listenobjekt, mit dem zusätzlichen Vorteil einer OOP-freundlichen lengthEigenschaft.

Wie immer kann Ihr Kilometerstand variieren.

Naftuli Kay
quelle
19
Nur damit Sie wissen, können Sie einfach length = property(len)die einzeilige Wrapper-Funktion ausführen und überspringen und die Dokumentation / Selbstbeobachtung lenIhrer Immobilie beibehalten .
Tadhg McDonald-Jensen
17

Außerdem können lenSie auch verwenden operator.length_hint(erfordert Python 3.4+). Für einen Normalen sind listbeide gleichwertig, aber length_hintes ist möglich, die Länge eines Listeniterators zu ermitteln, was unter bestimmten Umständen nützlich sein kann:

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

Ist length_hintaber per Definition nur ein "Hinweis", so ist die meiste Zeit lenbesser.

Ich habe mehrere Antworten gesehen, die auf einen Zugriff hinweisen __len__. Dies ist in Ordnung, wenn es sich um integrierte Klassen wie handelt list, kann jedoch zu Problemen mit benutzerdefinierten Klassen führen, da len(und length_hint) einige Sicherheitsüberprüfungen implementiert werden. Beispielsweise erlauben beide keine negativen Längen oder Längen, die einen bestimmten Wert (den sys.maxsizeWert) überschreiten . Es ist also immer sicherer, die lenFunktion anstelle der __len__Methode zu verwenden!

MSeifert
quelle
8

Beantworten Sie Ihre Frage anhand der zuvor angegebenen Beispiele:

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

print items.__len__()
Shai Alon
quelle
15
In Python sind Namen, die mit Unterstrichen beginnen, semantisch nicht öffentliche Methoden und sollten von Benutzern nicht verwendet werden.
Aaron Hall
2
1 . __foo__: Dies ist nur eine Konvention, eine Möglichkeit für das Python-System, Namen zu verwenden, die nicht mit Benutzernamen in Konflikt stehen. 2 . _foo: Dies ist nur eine Konvention, mit der der Programmierer angeben kann, dass die Variable privat ist (was auch immer dies in Python bedeutet). 3 . __foo: Dies hat eine echte Bedeutung: Der Interpreter ersetzt diesen Namen durch _classname__foo, um sicherzustellen, dass sich der Name nicht mit einem ähnlichen Namen in einer anderen Klasse überschneidet. * Keine andere Form von Unterstrichen hat in der Python-Welt eine Bedeutung. * In diesen Konventionen gibt es keinen Unterschied zwischen Klasse, Variable, Global usw.
Shai Alon
4
Diese Fragen und Antworten
Aaron Hall
@ AaronHall aber für len Funktion ist es fast das gleiche. Bei sehr großen Variablen ist dies möglicherweise schneller. Ich verstehe jedoch Ihren Standpunkt und wir sollten len (obj) und nicht obj .__ len __ () verwenden.
Shai Alon
7

Und der Vollständigkeit halber (hauptsächlich pädagogisch) ist es möglich, ohne die len()Funktion zu verwenden. Ich würde dies nicht als gute Option dulden. PROGRAMMIEREN SIE NICHT WIE DIESES IN PYTHON , aber es dient einem Zweck zum Lernen von Algorithmen.

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

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

(Der Doppelpunkt in list[:]ist implizit und daher auch optional.)

Die Lektion für neue Programmierer lautet: Sie können die Anzahl der Elemente in einer Liste nicht ermitteln, ohne sie irgendwann zu zählen. Die Frage lautet: Wann ist ein guter Zeitpunkt, um sie zu zählen? Beispielsweise connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);berechnet Hochleistungscode wie der Verbindungssystemaufruf für Sockets (in C geschrieben) nicht die Länge von Elementen (wobei diese Verantwortung dem aufrufenden Code übertragen wird). Beachten Sie, dass die Länge der Adresse weitergegeben wird, um den Schritt des Zählens der Länge zuerst zu speichern. Eine weitere Option: Rechnerisch kann es sinnvoll sein, die Anzahl der Elemente zu verfolgen, wenn Sie sie in das übergebene Objekt einfügen. Beachten Sie, dass dies mehr Speicherplatz beansprucht. Siehe Naftuli Kays Antwort .

Beispiel für das Verfolgen der Länge, um die Leistung zu verbessern und gleichzeitig mehr Speicherplatz zu beanspruchen. Beachten Sie, dass ich die Funktion len () nie verwende, da die Länge verfolgt wird:

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
Jonathan Komar
quelle
Warum for item in list[:]:? Warum nicht for item in list:? Außerdem würde ich verwenden, um += 1zu erhöhen.
Oma Schmerzen
@GrannyAching Ich habe den optionalen Doppelpunkt (Bereichsspezifizierer) ausdrücklich erwähnt. Ich habe den Bereichsspezifizierer zu Bildungszwecken dort belassen - es ist von Vorteil zu wissen, dass er impliziert ist. Ein Listentyp [] wird ebenfalls abgeleitet, wie Sie meinen Code vorschlagen. Der Inkrementoperator entspricht auch dem Hinzufügen von 1 zu einer vorhandenen Variablen, ist jedoch in allen Fällen kürzer. Ich würde also zustimmen, dass es verwendet werden sollte, wenn dies Ihre Argumentation ist. Dieser Code sollte sowieso nirgendwo in Produktion gehen (außer beim Erlernen der Programmierung).
Jonathan Komar
0

In Bezug auf die len()tatsächliche Funktionsweise ist dies die C-Implementierung :

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_tist die maximale Länge, die das Objekt haben kann. PyObject_Size()ist eine Funktion, die die Größe eines Objekts zurückgibt. Wenn die Größe eines Objekts nicht bestimmt werden kann, wird -1 zurückgegeben. In diesem Fall wird dieser Codeblock ausgeführt:

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

Infolgedessen wird eine Ausnahme ausgelöst. Andernfalls wird dieser Codeblock ausgeführt:

return PyLong_FromSsize_t(res);

resDies ist eine CGanzzahl, wird in eine Python konvertiert longund zurückgegeben. Alle Python-Ganzzahlen werden wie longsseit Python 3 gespeichert .

Alec Alameddine
quelle
3
Warum ist es wichtig, über die C-Implementierung Bescheid zu wissen oder Bescheid zu wissen?
CS95
Da diese Frage nicht spezifisch für CPython ist, kann diese Antwort irreführend sein. PyPy, IronPython, ... können und können es anders implementieren.
MSeifert