Frage Wie überprüfe ich, ob eine Liste leer ist?


Zum Beispiel, wenn das Folgende bestanden:

a = []

Wie überprüfe ich, ob? a ist leer?


2718
2017-09-10 06:20


Ursprung


Antworten:


if not a:
  print("List is empty")

Die implizite Boolesche Logik der leeren Liste ist ziemlich pythonisch.


3886
2017-09-10 06:28



Die pythonische Art, es zu tun, ist von der PEP 8 Style Guide (woher Ja bedeutet "empfohlen" und Nein bedeutet "nicht empfohlen"):

Verwenden Sie für Sequenzen (Strings, Listen, Tupel) die Tatsache, dass leere Sequenzen falsch sind.   

Ja: if not seq:
     if seq:

Nein:  if len(seq):
     if not len(seq):

862
2017-09-10 10:33



Ich bevorzuge es explizit:

if len(li) == 0:
    print('the list is empty')

So ist es 100% klar li ist eine Sequenz (Liste) und wir möchten ihre Größe testen. Mein Problem mit if not li: ... ist, dass es den falschen Eindruck gibt, dass li ist eine boolesche Variable.


517
2017-09-05 00:30



Andere Leute scheinen die Frage über Listen hinaus zu verallgemeinern, also dachte ich, ich würde einen Vorbehalt für eine andere Art von Sequenz hinzufügen, die viele Leute benutzen könnten, besonders da dies der erste Google-Treffer für "leeres python-Array" ist. .

Andere Methoden funktionieren nicht für numme Arrays

Sie müssen vorsichtig mit numpy Arrays sein, weil andere Methoden, die gut funktionieren lists oder andere Standardcontainer schlagen für numpy Arrays fehl. Ich erkläre, warum unten, aber kurz gesagt, die bevorzugte Methode ist zu benutzen size.

Der "pythonische" Weg funktioniert nicht: Teil 1

Der "pythonische" Weg schlägt mit numpy Arrays fehl, weil numpy versucht, das Array auf ein Array von zu werfen bools und if x versucht all diese zu bewerten bools sofort für irgendeine Art von Gesamtwahrheit Wert. Aber das macht keinen Sinn, also bekommst du ein ValueError:

>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Der "pythonische" Weg funktioniert nicht: Teil 2

Aber zumindest der Fall oben sagt dir, dass es fehlgeschlagen ist. Wenn Sie ein numpliges Array mit genau einem Element haben, wird das if Anweisung wird "funktionieren", in dem Sinne, dass Sie keinen Fehler erhalten. Wenn jedoch dieses eine Element zufällig ist 0 (oder 0.0, oder false, ...), das if Anweisung wird falsch ergeben false:

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

Aber klar x existiert und ist nicht leer! Dieses Ergebnis ist nicht das, was Sie wollten.

Verwenden len kann zu unerwarteten Ergebnissen führen

Beispielsweise,

len( numpy.zeros((1,0)) )

gibt 1 zurück, obwohl das Array keine Elemente enthält.

Der numpythonische Weg

Wie in der scipy FAQ, ist die korrekte Methode in allen Fällen, in denen Sie wissen, dass Sie ein numpy Array verwenden if x.size:

>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x

>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x

>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x

Wenn Sie nicht sicher sind, ob es sich um eine list, ein numpliges Array oder etwas anderes, können Sie diesen Ansatz mit kombinieren Die Antwort @dubiousjim gibt um sicherzustellen, dass für jeden Typ der richtige Test verwendet wird. Nicht sehr "pythonisch", aber es stellt sich heraus, dass in diesem Sinne absichtlich die Pythonizität durch Numpty gebrochen wurde.

Wenn Sie mehr tun müssen als nur zu überprüfen, ob die Eingabe leer ist und andere Funktionen wie Indizierung oder mathematische Operationen verwenden, ist es wahrscheinlich effizienter (und sicherlich häufiger), die Eingabe zu erzwingen sein ein numpliges Array. Dafür gibt es ein paar nette Funktionen - vor allem numpy.asarray. Dies nimmt Ihre Eingabe, macht nichts, wenn es bereits ein Array ist, oder wickelt Ihre Eingabe in ein Array um, wenn es sich um eine Liste, ein Tupel usw. handelt, und konvertiert sie optional in Ihre Auswahl dtype. Es ist also sehr schnell, wann immer es möglich ist, und es stellt sicher, dass Sie nur annehmen, dass die Eingabe ein numpliges Array ist. Wir verwenden normalerweise nur denselben Namen, da die Umwandlung in ein Array nicht außerhalb des aktuellen Bereichs erfolgt Umfang:

x = numpy.asarray(x, dtype=numpy.double)

Dies wird die x.size Überprüfen Sie die Arbeit in allen Fällen, die ich auf dieser Seite sehe.


208
2018-02-21 16:48



Eine leere Liste wird selbst im Echtwerttest als falsch betrachtet (siehe Python-Dokumentation):

a = []
if a:
     print "not empty"

@Daren Thomas

EDIT: Ein weiterer Punkt gegen das Testen   die leere Liste als False: Was ist mit   Polymorphismus? Du solltest dich nicht darauf verlassen   eine Liste ist eine Liste. Es sollte einfach   Quacksalber wie eine Ente - wie gehst du?   um deine enteCollection zu quaken   '' Falsch '' wenn es keine Elemente hat?

Ihre duckCollection sollte implementieren __nonzero__ oder __len__ also das wenn a: wird ohne Probleme funktionieren.


103
2017-09-10 06:31



Patricks Antwort (angenommen) ist richtig: if not a: ist der richtige Weg, es zu tun. Harley Holcombe's Antwort ist richtig, dass dies in der PEP 8 style guide ist. Aber was keine der Antworten erklärt, ist, warum es eine gute Idee ist, dem Idiom zu folgen - selbst wenn Sie persönlich finden, dass es nicht explizit genug oder verwirrend für Ruby-Benutzer oder was auch immer ist.

Python-Code und die Python-Community haben sehr starke Idiome. Wenn Sie diesen Idiomen folgen, wird Ihr Code für jeden, der mit Python vertraut ist, einfacher zu lesen. Und wenn Sie diese Idiome verletzen, ist das ein starkes Signal.

Es ist wahr, dass if not a: Unterscheidet nicht zwischen leeren Listen und None, oder numerische 0, oder leere Tupel, oder leere, vom Benutzer erstellte Sammlungstypen, oder leere, vom Benutzer erstellte Nicht-Sammlungstypen, oder Einzelelement-NumPy-Array, die als Skalare mit falschen Werten usw. fungieren. Und manchmal ist es wichtig zu sein explizit darüber. Und in diesem Fall weißt du es Was Sie möchten explizit sein, damit Sie genau das testen können. Beispielsweise, if not a and a is not None: bedeutet "alles falsch, außer keiner", während if len(a) != 0: bedeutet "nur leere Sequenzen - und alles außer einer Sequenz ist hier ein Fehler", und so weiter. Neben Tests für genau das, was Sie testen möchten, signalisiert dies dem Leser auch, dass dieser Test wichtig ist.

Aber wenn du nichts hast, worüber du explizit sein willst, irgendetwas anderes als if not a: führt den Leser in die Irre. Sie signalisieren etwas als wichtig, wenn es nicht ist. (Sie können den Code auch weniger flexibel oder langsamer machen, oder was auch immer, aber das ist alles weniger wichtig.) Und wenn Sie gewohnheitsmäßig den Leser so irreführen, dann wenn du machen muss unterschieden werden, es wird unbemerkt bleiben, weil du deinen Code "weinst".


81
2017-12-03 02:21



Der beste Weg, um zu überprüfen, ob eine Liste leer ist

Zum Beispiel, wenn das Folgende bestanden:

a = []

Wie überprüfe ich, ob a leer ist?

Kurze Antwort:

Platzieren Sie die Liste in einem booleschen Kontext (z. B. mit einem if oder whileErklärung). Es wird getestet False wenn es leer ist und True Andernfalls. Beispielsweise:

if not a:                           # do this!
    print('a is an empty list')

Appell an die Behörde

PEP 8, der offizielle Python-Style-Guide für Python-Code in der Python-Standardbibliothek, bestätigt:

Verwenden Sie für Sequenzen (Strings, Listen, Tupel) die Tatsache, dass leere Sequenzen falsch sind.

Yes: if not seq:
     if seq:

No: if len(seq):
    if not len(seq):

Wir sollten erwarten, dass der Standard-Bibliothekscode so performant und korrekt wie möglich sein sollte. Aber warum ist das der Fall und warum brauchen wir diese Anleitung?

Erläuterung

Ich sehe häufig Code von erfahrenen Programmierern, die neu in Python sind:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

Und Benutzer von faulen Sprachen könnten versucht sein, dies zu tun:

if a == []:                         # Don't do this!
    print('a is an empty list')

Diese sind in ihren jeweiligen anderen Sprachen korrekt. Und das ist in Python sogar semantisch korrekt.

Aber wir betrachten es als unpythonisch, weil Python diese Semantik direkt über boolesche Zwangsbedingungen in der Oberfläche des Listenobjekts unterstützt.

Von dem Dokumente (und beachten Sie insbesondere die Aufnahme der leeren Liste, []):

Standardmäßig wird ein Objekt als wahr betrachtet, es sei denn, seine Klasse definiert es   entweder ein __bool__() Methode, die zurückgibt False oder ein __len__() Methode   das gibt Null zurück, wenn es mit dem Objekt aufgerufen wird. Hier werden die meisten der eingebauten Objekte als falsch angesehen:

  • Konstanten, die als falsch definiert sind: None und False.
  • Null eines beliebigen numerischen Typs: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • leere Sequenzen und Sammlungen: '', (), [], {}, set(), range(0)

Und die Datamodell-Dokumentation:

object.__bool__(self)

Wird aufgerufen, um Wahrheitswerttests und den integrierten Betrieb zu implementieren bool(); sollte zurückkehren False oder True. Wenn diese Methode nicht definiert ist,    __len__() wird aufgerufen, wenn es definiert ist, und das Objekt wird als wahr betrachtet, wenn sein Ergebnis ungleich Null ist. Wenn eine Klasse keine definiert __len__()   Noch __bool__()Alle Instanzen werden als wahr betrachtet.

und

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 definiert __bool__() Methode und wessen __len__() Methodenrückgaben Null wird in einem booleschen Kontext als falsch betrachtet.

Also statt dessen:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

oder dieses:

if a == []:                     # Don't do this!
    print('a is an empty list')

Mach das:

if not a:
    print('a is an empty list')

Was Pythonic macht, zahlt sich in der Regel aus:

Lohnt es sich? (Beachten Sie, dass weniger Zeit für eine äquivalente Operation besser ist :)

>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435

Für die Skalierung sind hier die Kosten für den Aufruf der Funktion und das Erstellen und Zurückgeben einer leeren Liste, die Sie von den Kosten der oben verwendeten Leerwertüberprüfungen abziehen können:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

Wir sehen das entweder Überprüfung der Länge mit der eingebauten Funktion len verglichen mit 0  oder Überprüfung gegen eine leere Liste ist viel weniger leistungsfähig als die eingebaute Syntax der Sprache wie dokumentiert.

Warum?

Für die len(a) == 0 prüfen:

Zuerst muss Python die Globals überprüfen, um zu sehen, ob len ist beschattet.

Dann muss es die Funktion laden aufrufen 0, und führe den Gleichheitsvergleich in Python (statt mit C) durch:

>>> import dis
>>> dis.dis(lambda: len([]) == 0)
  1           0 LOAD_GLOBAL              0 (len)
              2 BUILD_LIST               0
              4 CALL_FUNCTION            1
              6 LOAD_CONST               1 (0)
              8 COMPARE_OP               2 (==)
             10 RETURN_VALUE

Und für die [] == []es muss eine unnötige Liste erstellen und dann, wiederum, die Vergleichsoperation in Pythons virtueller Maschine (im Gegensatz zu C)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

Der "Pythonic" -Weg ist eine viel einfachere und schnellere Überprüfung, da die Länge der Liste im Objektinstanz-Header zwischengespeichert wird:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

Hinweise aus der C-Quelle und Dokumentation

PyVarObject

Dies ist eine Erweiterung von PyObject das fügt das hinzu ob_size Feld. Dies wird nur für Objekte verwendet, die eine gewisse Länge haben. Dieser Typ wird häufig nicht in der Python / C-API angezeigt. Es entspricht den Feldern, die durch die Erweiterung der PyObject_VAR_HEAD Makro.

Von der c Quelle in Einschließen / listobject.h:

typedef struct {
    PyObject_VAR_HEAD
    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */
    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number
     * currently in use is ob_size.
     * Invariants:
     *     0 <= ob_size <= allocated
     *     len(list) == ob_size

Ich habe es genossen, dies zu erforschen, und ich verbringe viel Zeit damit, meine Antworten zu kuratieren. Wenn du denkst, dass ich etwas verlasse, lass es mich in einem Kommentar wissen.


80
2017-08-20 03:50



Ich habe das Folgende als bevorzugt angesehen:

if not a:
    print("The list is empty or null")

62
2017-09-10 06:28