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
?
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
?
Antworten:
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.
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 .
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.
len
implementiert 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.
len
Länge Sie erhalten könnenUnd 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
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:
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 items
oder if not items
ist sowohl lesbarer als auch performanter.
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 :
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 length
Eigenschaft.
Wie immer kann Ihr Kilometerstand variieren.
length = property(len)
die einzeilige Wrapper-Funktion ausführen und überspringen und die Dokumentation / Selbstbeobachtung len
Ihrer Immobilie beibehalten .
Außerdem können len
Sie auch verwenden operator.length_hint
(erfordert Python 3.4+). Für einen Normalen sind list
beide gleichwertig, aber length_hint
es 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_hint
aber per Definition nur ein "Hinweis", so ist die meiste Zeit len
besser.
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.maxsize
Wert) überschreiten . Es ist also immer sicherer, die len
Funktion anstelle der __len__
Methode zu verwenden!
Beantworten Sie Ihre Frage anhand der zuvor angegebenen Beispiele:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__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.
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
for item in list[:]:
? Warum nicht for 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 :
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
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:
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);
res
Dies ist eine C
Ganzzahl, wird in eine Python konvertiert long
und zurückgegeben. Alle Python-Ganzzahlen werden wie longs
seit Python 3 gespeichert .