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()
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.
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:
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):@propertydef 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.
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!
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.
@ 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.
(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:
classMyList(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 classdef __iter__(self):for elem in self._data:yield elem
def add(self, elem):
self._data.append(elem)
self.length +=1def 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
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).
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;}returnPyLong_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:
returnPyLong_FromSsize_t(res);
resDies ist eine CGanzzahl, wird in eine Python konvertiert longund zurückgegeben. Alle Python-Ganzzahlen werden wie longsseit Python 3 gespeichert .
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.
Antworten:
Die
len()
Funktion kann in Python mit verschiedenen Typen verwendet werden - sowohl mit integrierten Typen als auch mit Bibliothekstypen. Zum Beispiel:Die offizielle 2.x-Dokumentation finden Sie hier: Die offizielle 3.x-Dokumentation finden Sie hier:
len()
len()
quelle
Verwenden Sie die integrierte Funktion, um die Größe einer Liste zu ermitteln
len
:Und nun:
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)
len
implementiert mit__len__
, aus dem Datenmodell docs :object.__len__(self)
Und wir können auch sehen, dass dies
__len__
eine Methode von Listen ist:gibt 3 zurück.
Eingebaute Typen, deren
len
Länge Sie erhalten könnenUnd tatsächlich sehen wir, dass wir diese Informationen für alle beschriebenen Typen erhalten können:
Nicht
len
zum Testen auf eine leere oder nicht leere Liste verwendenUm auf eine bestimmte Länge zu testen, testen Sie natürlich einfach die Gleichheit:
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:
Tun Sie stattdessen einfach:
oder
Ich erkläre warum hier aber kurz
if items
oderif not items
ist sowohl lesbarer als auch performanter.quelle
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
length
Eigenschaft zu erstellen :Sie können es so verwenden:
Im Wesentlichen ist es genau identisch mit einem Listenobjekt, mit dem zusätzlichen Vorteil einer OOP-freundlichen
length
Eigenschaft.Wie immer kann Ihr Kilometerstand variieren.
quelle
length = property(len)
die einzeilige Wrapper-Funktion ausführen und überspringen und die Dokumentation / Selbstbeobachtunglen
Ihrer Immobilie beibehalten .Außerdem können
len
Sie auch verwendenoperator.length_hint
(erfordert Python 3.4+). Für einen Normalen sindlist
beide gleichwertig, aberlength_hint
es ist möglich, die Länge eines Listeniterators zu ermitteln, was unter bestimmten Umständen nützlich sein kann:Ist
length_hint
aber per Definition nur ein "Hinweis", so ist die meiste Zeitlen
besser.Ich habe mehrere Antworten gesehen, die auf einen Zugriff hinweisen
__len__
. Dies ist in Ordnung, wenn es sich um integrierte Klassen wie handeltlist
, kann jedoch zu Problemen mit benutzerdefinierten Klassen führen, dalen
(undlength_hint
) einige Sicherheitsüberprüfungen implementiert werden. Beispielsweise erlauben beide keine negativen Längen oder Längen, die einen bestimmten Wert (densys.maxsize
Wert) überschreiten . Es ist also immer sicherer, dielen
Funktion anstelle der__len__
Methode zu verwenden!quelle
Beantworten Sie Ihre Frage anhand der zuvor angegebenen Beispiele:
quelle
__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.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.(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:
quelle
for item in list[:]:
? Warum nichtfor item in list:
? Außerdem würde ich verwenden, um+= 1
zu erhöhen.In Bezug auf die
len()
tatsächliche Funktionsweise ist dies die C-Implementierung :Py_ssize_t
ist 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:Infolgedessen wird eine Ausnahme ausgelöst. Andernfalls wird dieser Codeblock ausgeführt:
res
Dies ist eineC
Ganzzahl, wird in eine Python konvertiertlong
und zurückgegeben. Alle Python-Ganzzahlen werden wielongs
seit Python 3 gespeichert .quelle