Ist arr .__ len __ () der bevorzugte Weg, um die Länge eines Arrays in Python zu ermitteln?

727

Ist in Python die folgende Möglichkeit, die Anzahl der Elemente zu ermitteln?

arr.__len__()

Wenn ja, warum die seltsame Syntax?

Joan Venge
quelle

Antworten:

1228
my_list = [1,2,3,4,5]
len(my_list)
# 5

Das gleiche gilt für Tupel:

my_tuple = (1,2,3,4,5)
len(my_tuple)
# 5

Und Strings, die eigentlich nur Anordnungen von Zeichen sind:

my_string = 'hello world'
len(my_string)
# 11

Dies wurde absichtlich so gemacht, dass Listen, Tupel und andere Containertypen oder Iterables nicht alle explizit eine öffentliche .length()Methode implementieren mussten. Stattdessen können Sie einfach len()alles überprüfen, was die 'magische' __len__()Methode implementiert .

Sicher, dies mag überflüssig erscheinen, aber Implementierungen zur Längenprüfung können selbst innerhalb derselben Sprache erheblich variieren. Es ist nicht ungewöhnlich, dass ein Sammlungstyp eine .length()Methode verwendet, während ein anderer Typ eine .lengthEigenschaft verwendet, während ein anderer verwendet .count(). Ein Schlüsselwort auf Sprachebene vereinheitlicht den Einstiegspunkt für alle diese Typen. Selbst Objekte, die Sie möglicherweise nicht als Listen von Elementen betrachten, können dennoch auf ihre Länge überprüft werden. Dies umfasst Zeichenfolgen, Warteschlangen, Bäume usw.

Die funktionale Natur von len()eignet sich auch gut für funktionale Programmierstile.

lengths = map(len, list_of_containers)
Soviut
quelle
8
len () ist ein Sprachbefehl, __len __ () ist eine Methode für Containertypen.
Soviut
33
len () ist eine globale, eingebaute Funktion; __len __ () ist eine Methode, die das Objekt implementieren kann. len (foo) ruft normalerweise foo .__ len __ () auf.
Tim Lesher
13
Sie erwähnen, dass durch die Angabe von len () nicht jeder Container eine .length () -Methode implementieren muss, aber wie unterscheidet sich dies, wenn jeder Typ immer noch eine __len __ () -Methode implementiert, die sowieso von len () aufgerufen wird? Werden verschiedene Containertypen von len () unterschiedlich behandelt?
Simon B. Jensen
10
@ Simon: Das bisschen über "müssen nicht alle .length () implementieren" ist verwirrend. Containertypen müssen noch eine Methode zur Rückgabe ihrer Länge implementieren. Der Punkt ist, dass es sich um ein standardisiertes Protokoll handelt, nicht um eine Ad-hoc-Methode, nach der Sie für jeden Typ suchen müssen. Die doppelten Unterstriche kennzeichnen dies.
Carl Meyer
16
Ich stimme Carl Meyer zu - zu sagen, dass eine öffentliche .length () -Methode nicht "explizit implementiert" werden muss, ist irreführend und im Kern falsch. Alles muss noch len implementieren und kann immer einfach eine eigene Längenmethode mit dem Namen beliebig implementieren - die len-Funktion umgehen. Ich sehe das wirklich als eine willkürliche Verrücktheit, die dazu passt, wie Guido die Welt sieht. Es hat wahrscheinlich nichts mit einer universellen Argumentation zu tun.
BT
52

Die Art und Weise, wie Sie eine Länge von allem nehmen, für das dies sinnvoll ist (eine Liste, ein Wörterbuch, ein Tupel, eine Zeichenfolge, ...), besteht darin, es aufzurufen len.

l = [1,2,3,4]
s = 'abcde'
len(l) #returns 4
len(s) #returns 5

Der Grund für die „seltsame“ Syntax ist , dass intern Python übersetzt len(object)in object.__len__(). Dies gilt für jedes Objekt. Wenn Sie also eine Klasse definieren und es sinnvoll ist, dass sie eine Länge hat, definieren Sie einfach eine __len__()Methode, und dann können Sie lendiese Instanzen aufrufen .

rz.
quelle
23

Python verwendet die Ententypisierung : Es ist ihm egal, was ein Objekt ist , solange es über die entsprechende Schnittstelle für die jeweilige Situation verfügt. Wenn Sie die integrierte Funktion len () für ein Objekt aufrufen, rufen Sie tatsächlich dessen interne __len__- Methode auf. Ein benutzerdefiniertes Objekt kann diese Schnittstelle implementieren und len () gibt die Antwort zurück, auch wenn das Objekt konzeptionell keine Sequenz ist.

Eine vollständige Liste der Schnittstellen finden Sie hier: http://docs.python.org/reference/datamodel.html#basic-customization

OnkelZeiv
quelle
23

Der bevorzugte Weg, um die Länge eines Python-Objekts zu ermitteln, besteht darin, es als Argument an die lenFunktion zu übergeben. Intern versucht Python dann, die spezielle __len__Methode des übergebenen Objekts aufzurufen .

David Locke
quelle
22

Verwenden Sie einfach len(arr):

>>> import array
>>> arr = array.array('i')
>>> arr.append('2')
>>> arr.__len__()
1
>>> len(arr)
1
Tim Lesher
quelle
10

Sie können len(arr) wie in den vorherigen Antworten vorgeschlagen verwenden, um die Länge des Arrays zu ermitteln. Wenn Sie die Abmessungen eines 2D-Arrays möchten, können Sie die arr.shapeHöhe und Breite der Rückgabe verwenden

Ahmed Abobakr
quelle
7

len(list_name)Die Funktion verwendet die Liste als Parameter und ruft die __len__()Funktion der Liste auf .

Harun ERGUL
quelle
1

Python schlägt vor, dass Benutzer len()anstelle von __len__()Konsistenz verwenden, genau wie andere Leute sagten. Es gibt jedoch noch einige andere Vorteile:

Für einige , wie in gebauten Typen list, str, bytearrayund so weiter, die Cython Umsetzung len()erfolgt eine Verknüpfung. Es gibt direkt die ob_sizein einer C-Struktur zurück, die schneller als das Aufrufen ist __len__().

Wenn Sie an solchen Details interessiert sind, können Sie das Buch "Fluent Python" von Luciano Ramalho lesen. Es enthält viele interessante Details, die Ihnen helfen können, Python besser zu verstehen.

JOHNKYON
quelle