Teufelsanwalt spielen. Ich verstehe nicht, warum diese Redewendung als pythonisch angesehen wird. "Explizit ist besser als implizit", richtig? Diese Überprüfung scheint nicht sehr explizit zu sein, was überprüft wird.
James McMahon
222
@JamesMcMahon - es ist ein Kompromiss zwischen expliziter und typischer Flexibilität. Im Allgemeinen bedeutet "explizit sein", keine "magischen" Dinge zu tun. Auf der anderen Seite bedeutet "Ententypisierung", mit allgemeineren Schnittstellen zu arbeiten, anstatt explizit nach Typen zu suchen. So etwas wie if a == []zwingt einen bestimmten Typ ( () == []ist False). Hier scheint allgemeiner Konsens zu bestehen, dass die Typisierung von Enten gewinnt (in der Tat, dies __nonzero__ist die Schnittstelle zum Testen der Leere docs.python.org/reference/datamodel.html#object.__nonzero__ )
andrew cooke
38
Diese Methode funktioniert nicht bei Numpy-Arrays. Ich denke also, wenn len (a) == 0 sowohl in Bezug auf "Ententypisierung" als auch implizit vorzuziehen ist.
Mr.WorshipMe
10
Die kanonische Methode, um festzustellen, ob ein Array in C leer ist, besteht darin, das erste Element zu dereferenzieren und zu prüfen, ob es null ist, vorausgesetzt, ein Array ist nicht terminiert. Andernfalls ist der Vergleich seiner Länge mit Null völlig ineffizient, wenn das Array eine signifikante Größe hat. Außerdem würden Sie normalerweise keinen Speicher für ein leeres Array zuweisen (der Zeiger bleibt null), sodass es keinen Sinn macht, zu versuchen, seine Länge zu ermitteln. Ich sage nicht, dass len (a) == 0 kein guter Weg ist, es zu tun, es schreit mir einfach nicht 'C', wenn ich es sehe.
Sleblanc
6
@BrennenSprimont, Wenn es nicht nullterminiert ist, kennen Sie bereits die Länge, ob es in einer separaten Variablen gespeichert ist oder Ihr Array in einen Container eingeschlossen ist, der die Länge verfolgt. C ++, Java, C # haben solche Container und implementieren eine "Längen" -Methode effizient. C hat so etwas nicht , du musst dein eigenes rollen. Statisch zugewiesene C-Arrays sind nur Zeiger auf einen Speicherplatz, der garantiert über genügend Speicherplatz verfügt, um die von Ihnen angeforderte Datenmenge zu speichern. In C ist nichts eingebaut, was Sie wissen lässt, wie viel Sie diesen Raum bereits gefüllt haben.
Sleblanc
1159
Die pythonische Methode dazu stammt aus dem PEP 8- Styleguide (wobei Ja „empfohlen“ und Nein „nicht empfohlen“ bedeutet):
Verwenden Sie für Sequenzen (Zeichenfolgen, Listen, Tupel) die Tatsache, dass leere Sequenzen falsch sind.
Der zweite Weg scheint besser zu sein, wenn Sie signalisieren möchten, dass seqes sich um ein listähnliches Objekt handelt.
BallpointBen
5
@BallpointBen, der, wie Pythonismus-Befürworter sagen würden, so weit wie möglich implizit in der Art und Weise sein sollte, wie die Variable benannt wird
axolotl
9
@BallpointBen versuchen Python mit Typ - Hinting für die Signalisierung , was eine Variable sein sollte. Es wurde in 3.5 eingeführt.
Boris
8
numpy hat diese Redewendung gebrochen ... seq = numpy.array ([1,2,3]), gefolgt von seq, wenn nicht, löst eine Ausnahme aus. "ValueError: Der Wahrheitswert eines Arrays mit mehr als einem Element ist nicht eindeutig. Verwenden Sie a.any () oder a.all () "
Mr.WorshipMe
2
@ Jeronimo: Ich glaube, das ist eine lxml-spezifische Warnung.
Harley Holcombe
767
Ich bevorzuge es ausdrücklich:
if len(li)==0:print('the list is empty')
Auf diese Weise ist zu 100% klar, dass lies sich um eine Sequenz (Liste) handelt, und wir möchten ihre Größe testen. Mein Problem dabei if not li: ...ist, dass es den falschen Eindruck vermittelt, dass lies sich um eine boolesche Variable handelt.
Es ist hässlich und unpythonisch zu überprüfen, ob die Länge einer Liste gleich Null ist, anstatt nur zu überprüfen, ob die Liste falsch ist. Jeder, der mit Python vertraut ist, wird nicht denken, dass er überhaupt liein Idiot ist, und es ist ihm egal. Wenn es wichtig ist, sollten Sie einen Kommentar hinzufügen, nicht mehr Code.
Carl Smith
21
Dies scheint ein unnötig präziser Test zu sein, der oft langsamer und meiner Meinung nach immer weniger lesbar ist. Anstatt die Größe von etwas Leerem zu überprüfen, prüfen Sie doch einfach, ob es leer ist.
John B
34
Der Grund, warum dies schlecht ist (und dass das Verletzen von Redewendungen in einer Sprache mit starken Redewendungen wie Python im Allgemeinen schlecht ist), ist, dass es dem Leser signalisiert, dass Sie die Länge aus irgendeinem Grund speziell überprüfen (z. B. weil Sie Noneoder wollen 0eine Ausnahme auslösen anstatt zu bestehen). Also, wenn Sie es ohne Grund tun, das ist irreführend-und es bedeutet auch , dass , wenn Ihr Code tut Notwendigkeit , den Unterschied zu machen, die Unterscheidung unsichtbar ist , weil Sie „ rufe Wolf“ auf dem ganzen Rest der Quelle haben.
Abarnert
18
Ich denke, das verlängert den Code nur unnötig. Warum nicht noch "expliziter" mit if bool(len(li) == 0) is True:?
Augurar
11
@Jabba ist in vielen Fällen O (1) (bei denen Sie mit den integrierten Datentypen arbeiten), aber darauf können Sie sich einfach nicht verlassen. Möglicherweise arbeiten Sie mit einem benutzerdefinierten Datentyp, der diese Eigenschaft nicht hat. Sie können diesen benutzerdefinierten Datentyp auch später hinzufügen, nachdem Sie diesen Code bereits geschrieben haben.
Ralokt
324
Dies ist der erste Google-Treffer für "Python Test Empty Array" und ähnliche Abfragen, und andere Leute scheinen die Frage über reine Listen hinaus zu verallgemeinern. Daher dachte ich, ich würde eine Einschränkung für eine andere Art von Sequenz hinzufügen, die viele Leute haben verwenden könnte.
Andere Methoden funktionieren nicht für NumPy-Arrays
Sie müssen mit NumPy-Arrays vorsichtig sein, da andere Methoden, die für lists oder andere Standardcontainer gut funktionieren , für NumPy-Arrays fehlschlagen. Ich erkläre unten, warum, aber kurz gesagt, die bevorzugte Methode ist die Verwendung size.
Der "pythonische" Weg funktioniert nicht: Teil 1
Die "pythonische" Methode schlägt bei NumPy-Arrays fehl, da NumPy versucht, das Array in ein Array von bools umzuwandeln , und if xversucht, alle diese bools gleichzeitig auf eine Art aggregierten Wahrheitswert zu bewerten. 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 obige Fall sagt Ihnen, dass es fehlgeschlagen ist. Wenn Sie zufällig ein NumPy-Array mit genau einem Element haben, if"funktioniert" die Anweisung in dem Sinne, dass Sie keinen Fehler erhalten. Wenn dieses eine Element jedoch zufällig 0(oder 0.0, oder False, ...) ist, führt die ifAnweisung fälschlicherweise zu False:
>>> x = numpy.array([0,])>>>if x:print("x")...else:print("No x")No x
Aber eindeutig xexistiert und ist nicht leer! Dieses Ergebnis ist nicht das, was Sie wollten.
Die Verwendung lenkann zu unerwarteten Ergebnissen führen
Zum Beispiel,
len( numpy.zeros((1,0)))
Gibt 1 zurück, obwohl das Array keine Elemente enthält.
Der numpythonische Weg
Wie in den SciPy-FAQ erläutert , ist die richtige Methode in allen Fällen, in denen Sie wissen, dass Sie ein NumPy-Array haben, folgende 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 ein listNumPy-Array oder etwas anderes handelt, können Sie diesen Ansatz mit der Antwort von @dubiousjim kombinieren , um sicherzustellen, dass für jeden Typ der richtige Test verwendet wird. Nicht sehr "pythonisch", aber es stellt sich heraus, dass NumPy zumindest in diesem Sinne absichtlich die Pythonizität gebrochen hat.
Wenn Sie mehr tun müssen, als nur zu überprüfen, ob die Eingabe leer ist, und andere NumPy-Funktionen wie Indizierung oder mathematische Operationen verwenden, ist es wahrscheinlich effizienter (und sicherlich häufiger), die Eingabe als NumPy-Array zu erzwingen . Es gibt ein paar nette Funktionen, um dies schnell zu erledigen - am wichtigsten numpy.asarray. Dies nimmt Ihre Eingabe, führt nichts aus, wenn es sich bereits um ein Array handelt, oder verpackt Ihre Eingabe in ein Array, wenn es sich um eine Liste, ein Tupel usw. handelt, und konvertiert sie optional in die von Ihnen ausgewählte dtype. Es ist also sehr schnell, wann immer es möglich ist, und es stellt sicher, dass Sie nur davon ausgehen können, dass die Eingabe ein NumPy-Array ist. Normalerweise verwenden wir sogar nur denselben Namen, da die Konvertierung in ein Array nicht außerhalb des aktuellen Bereichs erfolgt :
x = numpy.asarray(x, dtype=numpy.double)
Dadurch x.sizefunktioniert die Prüfung in allen Fällen, die ich auf dieser Seite sehe.
Es ist erwähnenswert, dass dies kein Fehler in Python ist, sondern eine absichtliche Vertragsunterbrechung durch numpy- numpyeine Bibliothek mit einem sehr spezifischen Anwendungsfall, und sie hat eine andere "natürliche" Definition dessen, was Wahrhaftigkeit auf einem Array für das ist Python-Standard für Container. Es macht Sinn, optimize für diesen Fall in der Weise , dass pathlibAnwendungen /zu verketten Pfade statt +- es ist nicht Standard, aber sinnvoll im Kontext.
Gareth Latty
9
Einverstanden. Mein Punkt ist nur, dass es wichtig ist, sich daran zu erinnern, dass Numpy die Entscheidung getroffen hat, das Tippen von Enten sowohl für die sehr verbreiteten if xals auch für die len(x)Redewendungen zu unterbrechen - und manchmal kann es sehr schwierig sein, einen Bruch zu erkennen und zu debuggen.
Mike
22
Ich weiß für mich nicht, ob eine Methode namens len (x) die Array-Länge aufgrund von Annahmen nicht zurückgibt, deren Name schlecht entworfen ist.
Dalton
11
Diese Frage hat nichts mit numpy Arrays zu tun
pppery
19
@ppperry Ja, die ursprüngliche Frage betraf nicht Numpy-Arrays, aber wenn Sie mit diesen und möglicherweise von Enten eingegebenen Argumenten arbeiten, wird diese Frage sehr relevant.
Peterhil
223
Am besten überprüfen Sie, ob eine Liste leer ist
Zum Beispiel, wenn Folgendes bestanden wurde:
a =[]
Wie überprüfe ich, ob a leer ist?
Kurze Antwort:
Platzieren Sie die Liste in einem booleschen Kontext (z. B. mit einer ifoder- whileAnweisung). Es wird getestet, Falseob es leer ist und Trueansonsten. Zum Beispiel:
ifnot a:# do this!print('a is an empty list')
PEP 8
PEP 8 , der offizielle Python-Styleguide für Python-Code in der Python-Standardbibliothek, behauptet:
Verwenden Sie für Sequenzen (Zeichenfolgen, Listen, Tupel) die Tatsache, dass leere Sequenzen falsch sind.
Wir sollten erwarten, dass der Standardbibliothekscode so performant und korrekt wie möglich ist. Aber warum ist das so und warum brauchen wir diese Anleitung?
Erläuterung
Ich sehe häufig Code wie diesen von erfahrenen Programmierern, die Python noch nicht kennen:
if len(a)==0:# Don't do this!print('a is an empty list')
Und Benutzer fauler 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.
Wir halten es jedoch für nicht pythonisch, da Python diese Semantik über booleschen Zwang direkt in der Schnittstelle des Listenobjekts unterstützt.
Aus den Dokumenten (und beachten Sie insbesondere die Aufnahme der leeren Liste []):
Standardmäßig wird ein Objekt als wahr betrachtet, es sei denn, seine Klasse definiert entweder eine __bool__()Methode, die zurückgibt, Falseoder eine __len__()Methode, die Null zurückgibt, wenn sie mit dem Objekt aufgerufen wird. Hier sind die meisten eingebauten Objekte, die als falsch angesehen werden:
Konstanten, die als falsch definiert sind: Noneund False.
Null jeden numerischen Typ: 0, 0.0, 0j, Decimal(0),Fraction(0, 1)
leere Sequenzen und Sammlungen: '', (), [], {}, set(),range(0)
Wird aufgerufen, um Wahrheitswerttests und den eingebauten Betrieb zu implementieren bool(). sollte zurückkehren Falseoder True. Wenn diese Methode nicht definiert ist,
__len__()wird sie aufgerufen, wenn sie definiert ist, und das Objekt wird als wahr betrachtet, wenn sein Ergebnis ungleich Null ist. Wenn eine Klasse weder __len__()
noch definiert __bool__(), werden alle ihre Instanzen als wahr betrachtet.
Wird aufgerufen, um die integrierte Funktion zu implementieren len(). Sollte die Länge des Objekts zurückgeben, eine Ganzzahl> = 0. Außerdem wird ein Objekt, das keine __bool__()Methode definiert und dessen __len__()Methode Null zurückgibt, in einem booleschen Kontext als falsch betrachtet.
Also stattdessen:
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:
ifnot a:print('a is an empty list')
Das zu tun, was Pythonic normalerweise in der Leistung auszahlt:
Zahlt es sich aus? (Beachten Sie, dass weniger Zeit für eine gleichwertige Operation besser ist :)
Für die Skalierung sind hier die Kosten für den Aufruf der Funktion und die Erstellung und Rückgabe einer leeren Liste aufgeführt, die Sie möglicherweise von den Kosten für die oben verwendeten Leereprüfungen abziehen:
Wir sehen, dass entweder die Überprüfung der Länge mit der integrierten Funktion im lenVergleich zu 0oder die Überprüfung anhand einer leeren Liste viel weniger leistungsfähig ist als die Verwendung der integrierten Syntax der Sprache, wie dokumentiert.
Warum?
Zur len(a) == 0Kontrolle:
Zuerst muss Python die Globals überprüfen, um festzustellen, ob sie lenim Schatten liegen.
Dann muss es die Funktion aufrufen, laden 0und den Gleichheitsvergleich in Python durchführen (anstelle von C):
Und für das muss [] == []es eine unnötige Liste erstellen und dann erneut die Vergleichsoperation in Pythons virtueller Maschine ausführen (im Gegensatz zu C).
Dies ist eine Erweiterung PyObject, die das ob_sizeFeld hinzufügt . Dies wird nur für Objekte verwendet, die einen Längenbegriff haben. Dieser Typ wird in der Python / C-API nicht häufig angezeigt. Es entspricht den Feldern, die durch die Erweiterung des PyObject_VAR_HEADMakros definiert werden.
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
Antwort auf Kommentare:
Ich möchte darauf hinweisen, dass dies auch für den nicht leeren Fall gilt, obwohl es ziemlich hässlich ist, wie bei l=[]damals %timeit len(l) != 090,6 ns ± 8,3 ns, %timeit l != []55,6 ns ± 3,09, %timeit not not l38,5 ns ± 0,372. Aber not not ltrotz der dreifachen Geschwindigkeit wird es niemandem Spaß machen . Es sieht lächerlich aus. Aber die Geschwindigkeit gewinnt,
ich nehme an, das Problem besteht darin, mit Zeit zu testen, da dies gerade if l:ausreicht, aber überraschenderweise %timeit bool(l)101 ns ± 2,64 ns ergibt. Interessanterweise gibt es keine Möglichkeit, ohne diese Strafe zum Bool zu zwingen. %timeit list nutzlos, da keine Konvertierung stattfinden würde.
IPython-Magie %timeitist hier nicht völlig nutzlos:
In[1]: l =[]In[2]:%timeit l
20 ns ±0.155 ns per loop (mean ± std. dev. of 7 runs,100000000 loops each)In[3]:%timeit not l
24.4 ns ±1.58 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[4]:%timeit notnot l
30.1 ns ±2.16 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Wir können sehen, dass nothier für jede weitere ein bisschen lineare Kosten anfallen. Wir wollen die Kosten sehen, ceteris paribus , das heißt, alles andere ist gleich - wo alles andere so weit wie möglich minimiert wird:
In[5]:%timeit if l:pass22.6 ns ±0.963 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[6]:%timeit ifnot l:pass24.4 ns ±0.796 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[7]:%timeit ifnotnot l:pass23.4 ns ±0.793 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Schauen wir uns nun den Fall für eine leere Liste an:
In[8]: l =[1]In[9]:%timeit if l:pass23.7 ns ±1.06 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[10]:%timeit ifnot l:pass23.6 ns ±1.64 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)In[11]:%timeit ifnotnot l:pass26.3 ns ±1 ns per loop (mean ± std. dev. of 7 runs,10000000 loops each)
Was wir hier sehen können, ist, dass es kaum einen Unterschied macht, ob Sie eine tatsächliche boolan die Bedingungsprüfung oder die Liste selbst übergeben, und wenn überhaupt, ist es schneller, die Liste so wie sie ist zu geben.
Python ist in C geschrieben; es verwendet seine Logik auf der C-Ebene. Alles, was Sie in Python schreiben, ist langsamer. Und es wird wahrscheinlich um Größenordnungen langsamer sein, wenn Sie die in Python integrierten Mechanismen nicht direkt verwenden.
Ich möchte darauf hinweisen, dass dies auch für den nicht leeren Fall gilt, obwohl es ziemlich hässlich ist, wie bei l=[]damals %timeit len(l) != 090,6 ns ± 8,3 ns, %timeit l != []55,6 ns ± 3,09, %timeit not not l38,5 ns ± 0,372. Aber not not ltrotz der dreifachen Geschwindigkeit wird es niemandem Spaß machen . Es sieht lächerlich aus. Aber die Geschwindigkeit gewinnt
Gregory Morse
Ich nehme an, das Problem besteht darin, mit Zeit zu testen, da dies gerade if l:ausreicht, aber überraschenderweise %timeit bool(l)101 ns ± 2,64 ns ergibt. Interessanterweise gibt es keine Möglichkeit, ohne diese Strafe zum Bool zu zwingen. %timeit list nutzlos, da keine Konvertierung stattfinden würde.
Gregory Morse
138
Eine leere Liste selbst wird beim Testen von wahren Werten als falsch angesehen (siehe Python-Dokumentation ):
a =[]if a:print"not empty"
@ Daren Thomas
EDIT: Ein weiterer Punkt gegen das Testen der leeren Liste als False: Was ist mit Polymorphismus? Sie sollten sich nicht darauf verlassen, dass eine Liste eine Liste ist. Es sollte nur wie eine Ente quaken - wie bringen Sie Ihre duckCollection dazu, "False" zu quaken, wenn sie keine Elemente enthält?
Ihre duckCollection sollte implementieren __nonzero__oder __len__so, wenn a: ohne Probleme funktioniert.
@information_interchange Wenn Sie die Richtigkeit eines Werts explizit überprüfen möchten, verwenden Sie bool(). bool([]) == Falsewird Truewie erwartet auswerten .
August
103
Patricks (akzeptierte) Antwort ist richtig: if not a:ist der richtige Weg, es zu tun. Harley Holcombes Antwort ist richtig, dass dies im PEP 8 Style Guide steht. Keine der Antworten erklärt jedoch, warum es eine gute Idee ist, der Redewendung zu folgen - auch wenn Sie persönlich feststellen, dass sie für Ruby-Benutzer oder was auch immer nicht explizit genug oder verwirrend ist.
Python-Code und die Python-Community haben sehr starke Redewendungen. Wenn Sie diesen Redewendungen folgen, ist Ihr Code für alle, die mit Python vertraut sind, leichter zu lesen. Und wenn Sie diese Redewendungen verletzen, ist das ein starkes Signal.
Es ist wahr, dass if not a:leere Listen nicht von Noneoder numerische 0 oder leere Tupel oder leere, vom Benutzer erstellte Sammlungstypen oder leere, vom Benutzer erstellte nicht ganz Sammlungstypen oder ein NumPy-Array mit einem Element, das als Skalare mit Falsey fungiert, unterschieden werden Werte usw. Und manchmal ist es wichtig, dies ausdrücklich zu erwähnen. In diesem Fall wissen Sie, worüber Sie explizit sprechen möchten, und können genau das testen. if not a and a is not None:Bedeutet beispielsweise "alles Falsche außer Keine", während if len(a) != 0:"nur leere Sequenzen - und alles außer einer Sequenz ist hier ein Fehler" und so weiter bedeutet. Dies testet nicht nur genau das, was Sie testen möchten, sondern signalisiert dem Leser auch, dass dieser Test wichtig ist.
Aber wenn Sie nichts explizites haben, führt etwas anderes if not a:den Leser in die Irre. Sie signalisieren etwas so Wichtiges, wenn es nicht ist. (Sie können auch sein machen den Code weniger flexibel, oder langsamer, oder was auch immer, aber das ist alles weniger wichtig ist .) Und wenn Sie gewohnheitsmäßig die Leser wie diese täuschen, dann , wenn Sie tun müssen , eine Unterscheidung zu machen, es geht unbemerkt , weil passieren Sie haben überall in Ihrem Code "Wolf geweint".
Niemand scheint sich damit befasst zu haben, Ihre Notwendigkeit in Frage zu stellen, die Liste überhaupt zu testen. Da Sie keinen zusätzlichen Kontext angegeben haben, kann ich mir vorstellen, dass Sie diese Überprüfung möglicherweise gar nicht erst durchführen müssen, aber mit der Listenverarbeitung in Python nicht vertraut sind.
Ich würde argumentieren, dass der pythonischste Weg darin besteht, überhaupt nicht zu überprüfen, sondern nur die Liste zu verarbeiten. Auf diese Weise wird es das Richtige tun, ob leer oder voll.
a =[]for item in a:<do something with item><rest of code>
Dies hat den Vorteil, dass alle Inhalte von a gehandhabt werden können, ohne dass eine spezifische Überprüfung der Leere erforderlich ist. Wenn a leer ist, wird der abhängige Block nicht ausgeführt und der Interpreter fällt in die nächste Zeile durch.
Wenn Sie das Array tatsächlich auf Leere überprüfen müssen, sind die anderen Antworten ausreichend.
Die Sache ist, zu überprüfen, ob die Liste leer ist, ist ziemlich wichtig, zumindest für mich. Haben Sie darüber nachgedacht, ob ein Skript enthalten ist <rest of code>, das das Ergebnis der forSchleife verwenden könnte? Oder direkt einige Werte in verwenden a? Wenn das Skript für die Ausführung mit streng kontrollierten Eingaben ausgelegt ist, ist die Überprüfung möglicherweise etwas unnötig. In den meisten Fällen variiert die Eingabe jedoch, und eine Überprüfung ist in der Regel besser.
Amarth Gûl
Mit Respekt, nein. Was ich in Betracht zog, war jemand, der nicht genug über Python wusste, um zu wissen, dass "if <list>:" die richtige Antwort war, und fragte, wie man nach einer leeren Liste sucht. Dann bemerke ich eine Menge Antworten, die unterschiedliche Meinungen boten, aber keine schien das ursprüngliche Bedürfnis anzusprechen. Das habe ich mit meiner Antwort versucht - lassen Sie sie die Notwendigkeit prüfen, bevor Sie fortfahren. Ich glaube, ich habe dies in meiner Antwort ausdrücklich vorgeschlagen.
MrWonderful
AmarthGûl @ - Wie könnte man bekommen , die Ergebnisse aus der for - Schleife , um das Skript innerhalb <Code ruhen> verarbeitet werden? In einer Liste vielleicht? Oder vielleicht ein Diktat? In diesem Fall gilt dieselbe Logik. Ich verstehe nicht, wie sich die Eingabe von Variablen auf einen vernünftig gestalteten Code auswirken kann, bei dem die Verarbeitung einer leeren Liste eine schlechte Idee wäre.
MrWonderful
Ein bisschen alt, aber wenn Sie nur überprüft haben, ob die Liste leer ist, wiederholt Ihr Code für eine nicht leere Liste den Vorgang immer wieder, wenn OP einfach nach einer Überprüfungsoperation sucht. Stellen Sie sich ein Worst-Case-Szenario für diesen Code vor, wenn sich n der Unendlichkeit nähert ...
DJK
7
@DJK - Nein, ich denke du vermisst es immer noch. Vermutlich möchten Sie etwas mit einer Liste tun, wenn Sie eine haben. Was würden Sie anders machen, wenn es leer wäre? Früh zurück? Was ist, wenn es nicht leer ist? verarbeiten? Der Punkt ist jedoch, dass Sie wahrscheinlich nicht nach einer leeren Liste suchen müssen, sondern nur darüber iterieren und alles tun müssen, was Sie mit den Elementen tun wollten . Wenn es keine Elemente gibt, fallen Sie durch. Wenn es Elemente gibt, verarbeiten Sie diese nach Bedarf. Es geht NICHT darum, das Beispiel für eine leere Prüfung zu verwenden, sondern überhaupt nicht zu prüfen. Verarbeiten Sie einfach die Liste.
MrWonderful
66
len()ist eine O (1) -Operation für Python-Listen, Strings, Dicts und Sets. Python verfolgt intern die Anzahl der Elemente in diesen Containern.
if isinstance(a,(list, some, other, types, i, accept))andnot a:
do_stuff
welches mit -1 gewählt wurde. Ich bin mir nicht sicher, ob dies daran liegt, dass die Leser Einwände gegen die Strategie erhoben oder der Meinung waren, dass die Antwort in der vorgestellten Form nicht hilfreich war. Ich werde so tun, als wäre es das letztere, da - was auch immer als "pythonisch" gilt - dies die richtige Strategie ist. Sofern Sie dies nicht bereits ausgeschlossen haben oder bereit sind, Fälle zu behandeln, in denen dies abeispielsweise der Fall ist, Falsebenötigen Sie einen Test, der restriktiver ist als nur if not a:. Sie könnten so etwas verwenden:
if isinstance(a, numpy.ndarray)andnot a.size:
do_stuff
elif isinstance(a, collections.Sized)andnot a:
do_stuff
Der erste Test ist eine Antwort auf die Antwort von @ Mike oben. Die dritte Zeile könnte auch ersetzt werden durch:
elif isinstance(a,(list, tuple))andnot a:
Wenn Sie nur Instanzen bestimmter Typen (und ihrer Untertypen) akzeptieren möchten, oder mit:
elif isinstance(a,(list, tuple))andnot len(a):
Sie können ohne die explizite Typprüfung davonkommen, aber nur, wenn der umgebende Kontext Ihnen bereits versichert, dass dies aein Wert der Typen ist, für die Sie bereit sind, oder wenn Sie sicher sind, dass Typen, für die Sie nicht bereit sind, funktionieren um Fehler auszulösen (z. B. TypeErrorwenn Sie leneinen Wert aufrufen , für den er nicht definiert ist), den Sie verarbeiten möchten. Im Allgemeinen scheinen die "pythonischen" Konventionen diesen letzten Weg zu gehen. Drücke es wie eine Ente und lass es einen DuckError auslösen, wenn es nicht weiß, wie man quakt. Sie müssen sich jedoch noch überlegen, welche Art von Annahmen Sie treffen und ob die Fälle, auf die Sie nicht vorbereitet sind, wirklich an den richtigen Stellen fehlerhaft sind. Die Numpy-Arrays sind ein gutes Beispiel, auf das man sich nur blind verlassen kannlen oder der boolesche Typecast macht möglicherweise nicht genau das, was Sie erwarten.
Es ist ziemlich selten, dass Sie eine vollständige Liste von 6 Typen haben, die Sie akzeptieren möchten und für keine anderen Typen flexibel sind. Wenn Sie so etwas brauchen, möchten Sie wahrscheinlich ein ABC. In diesem Fall wäre es wahrscheinlich eines der stdlib-ABCs, wie collections.abc.Sizedoder collections.abc.Sequence, aber es könnte eines sein, auf das Sie selbst und register(list)auf schreiben . Wenn Sie tatsächlich Code haben, bei dem es wichtig ist, leere von anderen Falseys zu unterscheiden und auch Listen und Tupel von anderen Sequenzen zu unterscheiden, dann ist dies richtig - aber ich glaube nicht, dass Sie einen solchen Code haben.
Abarnert
13
Der Grund, warum die Leute das nicht mögen, ist, dass es in den meisten Fällen völlig unnötig ist. Python ist eine Sprache vom Typ Ente, und diese Ebene der defensiven Codierung behindert dies aktiv. Die Idee hinter Pythons Typsystem ist, dass die Dinge so lange funktionieren sollten, wie das übergebene Objekt in Funktionen funktioniert, wie es benötigt wird. Durch explizite Typprüfungen zwingen Sie den Anrufer, bestimmte Typen zu verwenden, was genau der Sprache entspricht. Während gelegentlich solche Dinge notwendig sind (ausgenommen, dass Zeichenfolgen nicht als Sequenzen behandelt werden), sind solche Fälle selten und fast immer am besten als schwarze Listen.
Gareth Latty
1
Wenn Sie wirklich überprüfen möchten, ob der Wert genau ist []und nicht etwas Falsches eines anderen Typs, dann ist dies sicherlich if a == []:erforderlich, anstatt mit isinstance herumzuspielen.
RemcoGerlich
2
Es gibt jedoch einige automatische Zwänge ==. Auf den ersten Blick kann ich keine identifizieren []. [] == ()zum Beispiel kehrt zurück False. Aber zum Beispiel frozenset()==set()kehrt zurück True. Es lohnt sich also, zumindest darüber nachzudenken, ob ein unerwünschter Typ dazu gezwungen werden könnte [](oder umgekehrt) a == [].
Dubiousjim
@RemcoGerlich - isinstance () ist immer noch vorzuziehen, anstatt eine leere Liste zum Vergleichen zu erstellen. Wie ein anderer hervorhob, kann der Gleichheitsoperator auch eine implizite Konvertierung einiger Typen aufrufen, was unerwünscht sein kann. Es gibt keinen Grund, jemals "a == []" zu codieren, und dieser Code würde definitiv als Fehler in einer Codeüberprüfung gekennzeichnet sein, an der ich teilgenommen habe , "sondern" gute Programmiertechnik ".
Alle anderen als die hier aufgeführten Werte werden berücksichtigt True
None
False
Null von beliebigen numerischen Typs, zum Beispiel 0, 0.0, 0j.
jede leere Sequenz, zum Beispiel, '', (), [].
jede leere Zuordnung zum Beispiel {}.
Instanzen von benutzerdefinierten Klassen, wenn die Klasse eine __bool__()oder __len__()Methode definiert , wenn diese Methode die Ganzzahl Null oder den Bool-Wert zurückgibt False.
Wie man sehen kann, leere Liste []ist falsy , so zu tun , was zu einem Booleschen Wert Sounds effizientesten durchgeführt werden würde:
@DJ_Stuffy_K behaupten, was in Unit-Tests eine leere Liste? Einfach benutzen assert(not myList). Wenn Sie auch behaupten möchten, dass das Objekt a ist list, können Sie verwenden assertIsInstance().
Sнаđошƒаӽ
24
Hier sind einige Möglichkeiten, wie Sie überprüfen können, ob eine Liste leer ist:
a =[]#the list
1) Der ziemlich einfache pythonische Weg:
ifnot a:print("a is empty")
In Python werden leere Container wie Listen, Tupel, Mengen, Dikte, Variablen usw. als angesehen False. Man könnte die Liste einfach als Prädikat behandeln ( Rückgabe eines Booleschen Wertes ). Und ein TrueWert würde anzeigen, dass er nicht leer ist.
2) Ein sehr expliziter Weg: Verwenden Sie die len(), um die Länge zu ermitteln und zu überprüfen, ob sie gleich ist 0:
if len(a)==0:print("a is empty")
3) Oder vergleichen Sie es mit einer anonymen leeren Liste:
if a ==[]:print("a is empty")
4) Eine andere, aber alberne Art zu tun ist exceptionund iter():
try:
next(iter(a))# list has elementsexceptStopIteration:print("Error: a is empty")
Dies wird langsamer, da Sie unnötigerweise eine zusätzliche leere Liste instanziieren.
Carl Meyer
32
Dies ist weniger lesbar als if not a:und bricht leichter. Bitte tu es nicht.
devsnd
Es gibt einen guten Punkt, der früher gemacht wurde, () == []ist auch gleich falsch. Obwohl mir gefällt, wie diese Implementierung if not a:alle Fälle abdeckt, sollte Ihr Beispiel ausreichen, wenn Sie definitiv eine Liste erwarten.
def list_test (L):if L isNone:print('list is None')elifnot L :print('list is empty')else:print('list has %d elements'% len(L))
list_test(None)
list_test([])
list_test([1,2,3])
Es ist manchmal gut, Nonegetrennt auf Leere zu prüfen, da dies zwei verschiedene Zustände sind. Der obige Code erzeugt die folgende Ausgabe:
list isNone
list is empty
list has 3 elements
Obwohl es nichts wert ist, Nonewas falsch ist. Wenn Sie also den Test für None-ness nicht trennen möchten , müssen Sie das nicht tun.
def list_test2 (L):ifnot L :print('list is empty')else:print('list has %d elements'% len(L))
list_test2(None)
list_test2([])
list_test2([1,2,3])
Es ist möglich, dass dies eine Ausnahme auslöst, wenn aes sich nicht um eine Liste handelt und akeine Methode __len__implementiert ist. Ich würde empfehlen:if isinstance(obj, list): if len(obj) == 0: print '...'
Sven Krüger
4
@ SvenKrüger nein. Der Operator andist in Python faul. Nichts danach andwird ausgeführt, wenn die vorherige Bedingung andfalsch ist.
ElmoVanKielmo
7
wir könnten ein einfaches verwenden, wenn sonst:
item_list=[]if len(item_list)==0:print("list is empty")else:print("list is not empty")
-1 - Um Verwirrung zu vermeiden, verwenden Sie keine reservierten Wörter für Variablennamen. Andernfalls kann es beim nächsten Aufruf zu einem überraschenden Verhalten kommen, z. B. "list ()" ... so etwas wie "TypeError: 'list' object is nicht aufrufbar "oder so.
MrWonderful
6
Wenn Sie überprüfen möchten, ob eine Liste leer ist:
l =[]if l:# do your stuff.
Wenn Sie überprüfen möchten, ob alle Werte in der Liste leer sind. Es wird jedoch Truefür eine leere Liste sein:
l =["",False,0,'',[],{},()]if all(bool(x)for x in l):# do your stuff.
Wenn Sie beide Fälle zusammen verwenden möchten:
def empty_list(lst):if len(lst)==0:returnFalseelse:return all(bool(x)for x in l)
all (bool (x) für x in l) ist wahr für eine leere Liste
gberger
5
Da ich mich von der Lösung von @ dubiousjim inspirieren lasse, schlage ich vor, zusätzlich zu prüfen, ob es sich um etwas Iterierbares handelt
import collections
def is_empty(a):returnnot a and isinstance(a, collections.Iterable)
Hinweis: Eine Zeichenfolge wird als iterierbar betrachtet. - Hinzufügen, and not isinstance(a,(str,unicode))wenn die leere Zeichenfolge ausgeschlossen werden soll
Overbroad; Dabei wird nur gefragt, ob eine Liste leer ist und nicht, ob etwas leer ist.
pppery
1
Wenn ich nicht zufrieden if a:wäre, wäre es, weil ich eine Ausnahme wollte, wenn aes keine Art Container wäre. (Als iterable können auch Iteratoren verwendet werden, die nicht sinnvoll auf Leere getestet werden können.)
Bitte geben Sie weitere Erklärungen dazu, wie es funktioniert, ohne "wenn" zu schreiben.
Ganeshdeshmukh
3
Dies ist weder ein Python noch ein vollständiges Beispiel. Außerdem wird bei jeder Begegnung eine leere Liste instanziiert. Tu das nicht.
MrWonderful
@ MrWonderful instanziiert nicht jedes Mal eine leere Liste. Es wird nur überprüft, ob die vorhandene Liste aleer ist oder nicht.
Tessaracter
@ MrWonderful Ich verstehe nicht, was es machtpythonic
Tessaracter
@ganeshdeshmukh, wenn Sie es verwenden a==[], wird true auf dem Python-Terminal gedruckt, wenn a leer ist. Andernfalls wird False ausgegeben. Sie können dies in einer if-Bedingung auch alsif(a==[])
Tessaracter
3
Sie können sogar versuchen, bool () wie folgt zu verwenden
a =[1,2,3];print bool(a);# it will return True
a =[];print bool(a);# it will return False
Ich liebe diese Art der Checkliste ist leer oder nicht.
Für diejenigen (wie ich), die es nicht wussten, bool()wird eine Python-Variable in einen Booleschen Wert konvertiert, sodass Sie die Wahrhaftigkeit oder Falschheit eines Werts speichern können , ohne eine if-Anweisung verwenden zu müssen. Ich denke, es ist weniger lesbar als nur eine Bedingung wie die akzeptierte Antwort zu verwenden, aber ich bin sicher, dass es andere gute Anwendungsfälle dafür gibt.
Galen Long
Dies ist in einem Ausdruck verwendbar und knapper.
Qneill
3
Verwenden Sie einfach is_empty () oder machen Sie eine Funktion wie: -
def is_empty(any_structure):if any_structure:print('Structure is not empty.')returnTrueelse:print('Structure is empty.')returnFalse
Es kann für jede Datenstruktur wie eine Liste, Tupel, ein Wörterbuch und vieles mehr verwendet werden. Mit diesen können Sie es viele Male mit nur aufrufen is_empty(any_structure).
Der Name is_emptydeutet darauf hin, dass es etwas zurückgibt. Aber wenn es so wäre, wäre das einfach etwas bool(any_structure), das Sie stattdessen verwenden sollten ( wenn Sie überhaupt ein brauchen bool).
Davis Herring
4
Warum wollen wir eine Variation davon bool, die (auch) Nachrichten in die Standardausgabe druckt?
Davis Herring
@DavisHerring Wir haben immer zwei Möglichkeiten, zuerst mit der Funktion zu drucken, andere verwenden die Rückgabevariable bool. Du hast die Wahl. Ich schreibe beide, damit Sie zwischen ihnen wählen können.
Vineet Jain
3
Ein einfacher Weg ist zu überprüfen, ob die Länge gleich Null ist.
Was mich hierher gebracht hat, ist ein spezieller Anwendungsfall: Ich wollte eigentlich eine Funktion , die mir sagt, ob eine Liste leer ist oder nicht. Ich wollte vermeiden, hier meine eigene Funktion zu schreiben oder einen Lambda-Ausdruck zu verwenden (weil es so schien, als ob es einfach genug sein sollte):
foo = itertools.takewhile(is_not_empty,(f(x)for x in itertools.count(1)))
Und natürlich gibt es einen sehr natürlichen Weg, dies zu tun:
foo = itertools.takewhile(bool,(f(x)for x in itertools.count(1)))
Natürlich müssen nicht verwendet werden boolin if(dh if bool(L):) , weil es impliziert wird . Aber für die Fälle, in denen "nicht leer" explizit als Funktion benötigt wird, boolist dies die beste Wahl.
Um zu überprüfen, ob eine Liste leer ist oder nicht, haben Sie zwei Möglichkeiten. Aber denken Sie daran, wir sollten es vermeiden, explizit nach einem Sequenztyp zu suchen (es ist ein less pythonicWeg):
def enquiry(list1):if len(list1)==0:return0else:return1# ––––––––––––––––––––––––––––––––
list1 =[]if enquiry(list1):print("The list isn't empty")else:print("The list is Empty")# Result: "The list is Empty".
Der zweite Weg ist ein more pythonicEins. Diese Methode ist eine implizite Methode zur Überprüfung und weitaus bevorzugter als die vorherige.
def enquiry(list1):ifnot list1:returnTrueelse:returnFalse# ––––––––––––––––––––––––––––––––
list1 =[]if enquiry(list1):print("The list is Empty")else:print("The list isn't empty")# Result: "The list is Empty"
if a == []
zwingt einen bestimmten Typ (() == []
istFalse
). Hier scheint allgemeiner Konsens zu bestehen, dass die Typisierung von Enten gewinnt (in der Tat, dies__nonzero__
ist die Schnittstelle zum Testen der Leere docs.python.org/reference/datamodel.html#object.__nonzero__ )Die pythonische Methode dazu stammt aus dem PEP 8- Styleguide (wobei Ja „empfohlen“ und Nein „nicht empfohlen“ bedeutet):
quelle
seq
es sich um ein listähnliches Objekt handelt.Ich bevorzuge es ausdrücklich:
Auf diese Weise ist zu 100% klar, dass
li
es sich um eine Sequenz (Liste) handelt, und wir möchten ihre Größe testen. Mein Problem dabeiif not li: ...
ist, dass es den falschen Eindruck vermittelt, dassli
es sich um eine boolesche Variable handelt.quelle
li
ein Idiot ist, und es ist ihm egal. Wenn es wichtig ist, sollten Sie einen Kommentar hinzufügen, nicht mehr Code.None
oder wollen0
eine Ausnahme auslösen anstatt zu bestehen). Also, wenn Sie es ohne Grund tun, das ist irreführend-und es bedeutet auch , dass , wenn Ihr Code tut Notwendigkeit , den Unterschied zu machen, die Unterscheidung unsichtbar ist , weil Sie „ rufe Wolf“ auf dem ganzen Rest der Quelle haben.if bool(len(li) == 0) is True:
?Dies ist der erste Google-Treffer für "Python Test Empty Array" und ähnliche Abfragen, und andere Leute scheinen die Frage über reine Listen hinaus zu verallgemeinern. Daher dachte ich, ich würde eine Einschränkung für eine andere Art von Sequenz hinzufügen, die viele Leute haben verwenden könnte.
Andere Methoden funktionieren nicht für NumPy-Arrays
Sie müssen mit NumPy-Arrays vorsichtig sein, da andere Methoden, die für
list
s oder andere Standardcontainer gut funktionieren , für NumPy-Arrays fehlschlagen. Ich erkläre unten, warum, aber kurz gesagt, die bevorzugte Methode ist die Verwendungsize
.Der "pythonische" Weg funktioniert nicht: Teil 1
Die "pythonische" Methode schlägt bei NumPy-Arrays fehl, da NumPy versucht, das Array in ein Array von
bool
s umzuwandeln , undif x
versucht, alle diesebool
s gleichzeitig auf eine Art aggregierten Wahrheitswert zu bewerten. Aber das macht keinen Sinn, also bekommst du einValueError
:Der "pythonische" Weg funktioniert nicht: Teil 2
Aber zumindest der obige Fall sagt Ihnen, dass es fehlgeschlagen ist. Wenn Sie zufällig ein NumPy-Array mit genau einem Element haben,
if
"funktioniert" die Anweisung in dem Sinne, dass Sie keinen Fehler erhalten. Wenn dieses eine Element jedoch zufällig0
(oder0.0
, oderFalse
, ...) ist, führt dieif
Anweisung fälschlicherweise zuFalse
:Aber eindeutig
x
existiert und ist nicht leer! Dieses Ergebnis ist nicht das, was Sie wollten.Die Verwendung
len
kann zu unerwarteten Ergebnissen führenZum Beispiel,
Gibt 1 zurück, obwohl das Array keine Elemente enthält.
Der numpythonische Weg
Wie in den SciPy-FAQ erläutert , ist die richtige Methode in allen Fällen, in denen Sie wissen, dass Sie ein NumPy-Array haben, folgende
if x.size
:Wenn Sie nicht sicher sind, ob es sich um ein
list
NumPy-Array oder etwas anderes handelt, können Sie diesen Ansatz mit der Antwort von @dubiousjim kombinieren , um sicherzustellen, dass für jeden Typ der richtige Test verwendet wird. Nicht sehr "pythonisch", aber es stellt sich heraus, dass NumPy zumindest in diesem Sinne absichtlich die Pythonizität gebrochen hat.Wenn Sie mehr tun müssen, als nur zu überprüfen, ob die Eingabe leer ist, und andere NumPy-Funktionen wie Indizierung oder mathematische Operationen verwenden, ist es wahrscheinlich effizienter (und sicherlich häufiger), die Eingabe als NumPy-Array zu erzwingen . Es gibt ein paar nette Funktionen, um dies schnell zu erledigen - am wichtigsten
numpy.asarray
. Dies nimmt Ihre Eingabe, führt nichts aus, wenn es sich bereits um ein Array handelt, oder verpackt Ihre Eingabe in ein Array, wenn es sich um eine Liste, ein Tupel usw. handelt, und konvertiert sie optional in die von Ihnen ausgewähltedtype
. Es ist also sehr schnell, wann immer es möglich ist, und es stellt sicher, dass Sie nur davon ausgehen können, dass die Eingabe ein NumPy-Array ist. Normalerweise verwenden wir sogar nur denselben Namen, da die Konvertierung in ein Array nicht außerhalb des aktuellen Bereichs erfolgt :Dadurch
x.size
funktioniert die Prüfung in allen Fällen, die ich auf dieser Seite sehe.quelle
numpy
-numpy
eine Bibliothek mit einem sehr spezifischen Anwendungsfall, und sie hat eine andere "natürliche" Definition dessen, was Wahrhaftigkeit auf einem Array für das ist Python-Standard für Container. Es macht Sinn, optimize für diesen Fall in der Weise , dasspathlib
Anwendungen/
zu verketten Pfade statt+
- es ist nicht Standard, aber sinnvoll im Kontext.if x
als auch für dielen(x)
Redewendungen zu unterbrechen - und manchmal kann es sehr schwierig sein, einen Bruch zu erkennen und zu debuggen.Kurze Antwort:
Platzieren Sie die Liste in einem booleschen Kontext (z. B. mit einer
if
oder-while
Anweisung). Es wird getestet,False
ob es leer ist undTrue
ansonsten. Zum Beispiel:PEP 8
PEP 8 , der offizielle Python-Styleguide für Python-Code in der Python-Standardbibliothek, behauptet:
Wir sollten erwarten, dass der Standardbibliothekscode so performant und korrekt wie möglich ist. Aber warum ist das so und warum brauchen wir diese Anleitung?
Erläuterung
Ich sehe häufig Code wie diesen von erfahrenen Programmierern, die Python noch nicht kennen:
Und Benutzer fauler Sprachen könnten versucht sein, dies zu tun:
Diese sind in ihren jeweiligen anderen Sprachen korrekt. Und das ist in Python sogar semantisch korrekt.
Wir halten es jedoch für nicht pythonisch, da Python diese Semantik über booleschen Zwang direkt in der Schnittstelle des Listenobjekts unterstützt.
Aus den Dokumenten (und beachten Sie insbesondere die Aufnahme der leeren Liste
[]
):Und die Dokumentation zum Datenmodell:
und
Also stattdessen:
oder dieses:
Mach das:
Das zu tun, was Pythonic normalerweise in der Leistung auszahlt:
Zahlt es sich aus? (Beachten Sie, dass weniger Zeit für eine gleichwertige Operation besser ist :)
Für die Skalierung sind hier die Kosten für den Aufruf der Funktion und die Erstellung und Rückgabe einer leeren Liste aufgeführt, die Sie möglicherweise von den Kosten für die oben verwendeten Leereprüfungen abziehen:
Wir sehen, dass entweder die Überprüfung der Länge mit der integrierten Funktion im
len
Vergleich zu0
oder die Überprüfung anhand einer leeren Liste viel weniger leistungsfähig ist als die Verwendung der integrierten Syntax der Sprache, wie dokumentiert.Warum?
Zur
len(a) == 0
Kontrolle:Zuerst muss Python die Globals überprüfen, um festzustellen, ob sie
len
im Schatten liegen.Dann muss es die Funktion aufrufen, laden
0
und den Gleichheitsvergleich in Python durchführen (anstelle von C):Und für das muss
[] == []
es eine unnötige Liste erstellen und dann erneut die Vergleichsoperation in Pythons virtueller Maschine ausführen (im Gegensatz zu C).Die "Pythonic" -Methode ist eine viel einfachere und schnellere Überprüfung, da die Länge der Liste im Objektinstanzheader zwischengespeichert wird:
Nachweise aus der C-Quelle und Dokumentation
Aus der c-Quelle in Include / listobject.h :
Antwort auf Kommentare:
IPython-Magie
%timeit
ist hier nicht völlig nutzlos:Wir können sehen, dass
not
hier für jede weitere ein bisschen lineare Kosten anfallen. Wir wollen die Kosten sehen, ceteris paribus , das heißt, alles andere ist gleich - wo alles andere so weit wie möglich minimiert wird:Schauen wir uns nun den Fall für eine leere Liste an:
Was wir hier sehen können, ist, dass es kaum einen Unterschied macht, ob Sie eine tatsächliche
bool
an die Bedingungsprüfung oder die Liste selbst übergeben, und wenn überhaupt, ist es schneller, die Liste so wie sie ist zu geben.Python ist in C geschrieben; es verwendet seine Logik auf der C-Ebene. Alles, was Sie in Python schreiben, ist langsamer. Und es wird wahrscheinlich um Größenordnungen langsamer sein, wenn Sie die in Python integrierten Mechanismen nicht direkt verwenden.
quelle
l=[]
damals%timeit len(l) != 0
90,6 ns ± 8,3 ns,%timeit l != []
55,6 ns ± 3,09,%timeit not not l
38,5 ns ± 0,372. Abernot not l
trotz der dreifachen Geschwindigkeit wird es niemandem Spaß machen . Es sieht lächerlich aus. Aber die Geschwindigkeit gewinntif l:
ausreicht, aber überraschenderweise%timeit bool(l)
101 ns ± 2,64 ns ergibt. Interessanterweise gibt es keine Möglichkeit, ohne diese Strafe zum Bool zu zwingen.%timeit l
ist nutzlos, da keine Konvertierung stattfinden würde.Eine leere Liste selbst wird beim Testen von wahren Werten als falsch angesehen (siehe Python-Dokumentation ):
@ Daren Thomas
Ihre duckCollection sollte implementieren
__nonzero__
oder__len__
so, wenn a: ohne Probleme funktioniert.quelle
[] == False
zu False ausgewertet wirdbool()
.bool([]) == False
wirdTrue
wie erwartet auswerten .Patricks (akzeptierte) Antwort ist richtig:
if not a:
ist der richtige Weg, es zu tun. Harley Holcombes Antwort ist richtig, dass dies im PEP 8 Style Guide steht. Keine der Antworten erklärt jedoch, warum es eine gute Idee ist, der Redewendung zu folgen - auch wenn Sie persönlich feststellen, dass sie für Ruby-Benutzer oder was auch immer nicht explizit genug oder verwirrend ist.Python-Code und die Python-Community haben sehr starke Redewendungen. Wenn Sie diesen Redewendungen folgen, ist Ihr Code für alle, die mit Python vertraut sind, leichter zu lesen. Und wenn Sie diese Redewendungen verletzen, ist das ein starkes Signal.
Es ist wahr, dass
if not a:
leere Listen nicht vonNone
oder numerische 0 oder leere Tupel oder leere, vom Benutzer erstellte Sammlungstypen oder leere, vom Benutzer erstellte nicht ganz Sammlungstypen oder ein NumPy-Array mit einem Element, das als Skalare mit Falsey fungiert, unterschieden werden Werte usw. Und manchmal ist es wichtig, dies ausdrücklich zu erwähnen. In diesem Fall wissen Sie, worüber Sie explizit sprechen möchten, und können genau das testen.if not a and a is not None:
Bedeutet beispielsweise "alles Falsche außer Keine", währendif len(a) != 0:
"nur leere Sequenzen - und alles außer einer Sequenz ist hier ein Fehler" und so weiter bedeutet. Dies testet nicht nur genau das, was Sie testen möchten, sondern signalisiert dem Leser auch, dass dieser Test wichtig ist.Aber wenn Sie nichts explizites haben, führt etwas anderes
if not a:
den Leser in die Irre. Sie signalisieren etwas so Wichtiges, wenn es nicht ist. (Sie können auch sein machen den Code weniger flexibel, oder langsamer, oder was auch immer, aber das ist alles weniger wichtig ist .) Und wenn Sie gewohnheitsmäßig die Leser wie diese täuschen, dann , wenn Sie tun müssen , eine Unterscheidung zu machen, es geht unbemerkt , weil passieren Sie haben überall in Ihrem Code "Wolf geweint".quelle
Warum überhaupt nachsehen?
Niemand scheint sich damit befasst zu haben, Ihre Notwendigkeit in Frage zu stellen, die Liste überhaupt zu testen. Da Sie keinen zusätzlichen Kontext angegeben haben, kann ich mir vorstellen, dass Sie diese Überprüfung möglicherweise gar nicht erst durchführen müssen, aber mit der Listenverarbeitung in Python nicht vertraut sind.
Ich würde argumentieren, dass der pythonischste Weg darin besteht, überhaupt nicht zu überprüfen, sondern nur die Liste zu verarbeiten. Auf diese Weise wird es das Richtige tun, ob leer oder voll.
Dies hat den Vorteil, dass alle Inhalte von a gehandhabt werden können, ohne dass eine spezifische Überprüfung der Leere erforderlich ist. Wenn a leer ist, wird der abhängige Block nicht ausgeführt und der Interpreter fällt in die nächste Zeile durch.
Wenn Sie das Array tatsächlich auf Leere überprüfen müssen, sind die anderen Antworten ausreichend.
quelle
<rest of code>
, das das Ergebnis derfor
Schleife verwenden könnte? Oder direkt einige Werte in verwendena
? Wenn das Skript für die Ausführung mit streng kontrollierten Eingaben ausgelegt ist, ist die Überprüfung möglicherweise etwas unnötig. In den meisten Fällen variiert die Eingabe jedoch, und eine Überprüfung ist in der Regel besser.len()
ist eine O (1) -Operation für Python-Listen, Strings, Dicts und Sets. Python verfolgt intern die Anzahl der Elemente in diesen Containern.JavaScript hat eine ähnliche Vorstellung von Wahrheit / Falschheit .
quelle
Ich hatte geschrieben:
welches mit -1 gewählt wurde. Ich bin mir nicht sicher, ob dies daran liegt, dass die Leser Einwände gegen die Strategie erhoben oder der Meinung waren, dass die Antwort in der vorgestellten Form nicht hilfreich war. Ich werde so tun, als wäre es das letztere, da - was auch immer als "pythonisch" gilt - dies die richtige Strategie ist. Sofern Sie dies nicht bereits ausgeschlossen haben oder bereit sind, Fälle zu behandeln, in denen dies
a
beispielsweise der Fall ist,False
benötigen Sie einen Test, der restriktiver ist als nurif not a:
. Sie könnten so etwas verwenden:Der erste Test ist eine Antwort auf die Antwort von @ Mike oben. Die dritte Zeile könnte auch ersetzt werden durch:
Wenn Sie nur Instanzen bestimmter Typen (und ihrer Untertypen) akzeptieren möchten, oder mit:
Sie können ohne die explizite Typprüfung davonkommen, aber nur, wenn der umgebende Kontext Ihnen bereits versichert, dass dies
a
ein Wert der Typen ist, für die Sie bereit sind, oder wenn Sie sicher sind, dass Typen, für die Sie nicht bereit sind, funktionieren um Fehler auszulösen (z. B.TypeError
wenn Sielen
einen Wert aufrufen , für den er nicht definiert ist), den Sie verarbeiten möchten. Im Allgemeinen scheinen die "pythonischen" Konventionen diesen letzten Weg zu gehen. Drücke es wie eine Ente und lass es einen DuckError auslösen, wenn es nicht weiß, wie man quakt. Sie müssen sich jedoch noch überlegen, welche Art von Annahmen Sie treffen und ob die Fälle, auf die Sie nicht vorbereitet sind, wirklich an den richtigen Stellen fehlerhaft sind. Die Numpy-Arrays sind ein gutes Beispiel, auf das man sich nur blind verlassen kannlen
oder der boolesche Typecast macht möglicherweise nicht genau das, was Sie erwarten.quelle
collections.abc.Sized
odercollections.abc.Sequence
, aber es könnte eines sein, auf das Sie selbst undregister(list)
auf schreiben . Wenn Sie tatsächlich Code haben, bei dem es wichtig ist, leere von anderen Falseys zu unterscheiden und auch Listen und Tupel von anderen Sequenzen zu unterscheiden, dann ist dies richtig - aber ich glaube nicht, dass Sie einen solchen Code haben.[]
und nicht etwas Falsches eines anderen Typs, dann ist dies sicherlichif a == []:
erforderlich, anstatt mit isinstance herumzuspielen.==
. Auf den ersten Blick kann ich keine identifizieren[]
.[] == ()
zum Beispiel kehrt zurückFalse
. Aber zum Beispielfrozenset()==set()
kehrt zurückTrue
. Es lohnt sich also, zumindest darüber nachzudenken, ob ein unerwünschter Typ dazu gezwungen werden könnte[]
(oder umgekehrt)a == []
.Aus der Dokumentation zur Wahrheitsprüfung:
Alle anderen als die hier aufgeführten Werte werden berücksichtigt
True
None
False
0
,0.0
,0j
.''
,()
,[]
.{}
.__bool__()
oder__len__()
Methode definiert , wenn diese Methode die Ganzzahl Null oder den Bool-Wert zurückgibtFalse
.Wie man sehen kann, leere Liste
[]
ist falsy , so zu tun , was zu einem Booleschen Wert Sounds effizientesten durchgeführt werden würde:quelle
assert(not myList)
. Wenn Sie auch behaupten möchten, dass das Objekt a istlist
, können Sie verwendenassertIsInstance()
.Hier sind einige Möglichkeiten, wie Sie überprüfen können, ob eine Liste leer ist:
1) Der ziemlich einfache pythonische Weg:
In Python werden leere Container wie Listen, Tupel, Mengen, Dikte, Variablen usw. als angesehen
False
. Man könnte die Liste einfach als Prädikat behandeln ( Rückgabe eines Booleschen Wertes ). Und einTrue
Wert würde anzeigen, dass er nicht leer ist.2) Ein sehr expliziter Weg: Verwenden Sie die
len()
, um die Länge zu ermitteln und zu überprüfen, ob sie gleich ist0
:3) Oder vergleichen Sie es mit einer anonymen leeren Liste:
4) Eine andere, aber alberne Art zu tun ist
exception
unditer()
:quelle
Ich bevorzuge folgendes:
quelle
if not a:
und bricht leichter. Bitte tu es nicht.() == []
ist auch gleich falsch. Obwohl mir gefällt, wie diese Implementierungif not a:
alle Fälle abdeckt, sollte Ihr Beispiel ausreichen, wenn Sie definitiv eine Liste erwarten.Methode 1 (bevorzugt):
Methode 2:
Methode 3:
quelle
Es ist manchmal gut,
None
getrennt auf Leere zu prüfen, da dies zwei verschiedene Zustände sind. Der obige Code erzeugt die folgende Ausgabe:Obwohl es nichts wert ist,
None
was falsch ist. Wenn Sie also den Test fürNone
-ness nicht trennen möchten , müssen Sie das nicht tun.produziert erwartet
quelle
Viele Antworten wurden gegeben, und viele von ihnen sind ziemlich gut. Ich wollte nur hinzufügen, dass der Scheck
wird auch für
None
und andere Arten von leeren Strukturen passieren . Wenn Sie wirklich nach einer leeren Liste suchen möchten, können Sie dies tun:quelle
a
es sich nicht um eine Liste handelt unda
keine Methode__len__
implementiert ist. Ich würde empfehlen:if isinstance(obj, list): if len(obj) == 0: print '...'
and
ist in Python faul. Nichts danachand
wird ausgeführt, wenn die vorherige Bedingungand
falsch ist.wir könnten ein einfaches verwenden, wenn sonst:
quelle
Wenn Sie überprüfen möchten, ob eine Liste leer ist:
Wenn Sie überprüfen möchten, ob alle Werte in der Liste leer sind. Es wird jedoch
True
für eine leere Liste sein:Wenn Sie beide Fälle zusammen verwenden möchten:
Jetzt können Sie verwenden:
quelle
Da ich mich von der Lösung von @ dubiousjim inspirieren lasse, schlage ich vor, zusätzlich zu prüfen, ob es sich um etwas Iterierbares handelt
Hinweis: Eine Zeichenfolge wird als iterierbar betrachtet. - Hinzufügen,
and not isinstance(a,(str,unicode))
wenn die leere Zeichenfolge ausgeschlossen werden sollPrüfung:
quelle
if a:
wäre, wäre es, weil ich eine Ausnahme wollte, wenna
es keine Art Container wäre. (Als iterable können auch Iteratoren verwendet werden, die nicht sinnvoll auf Leere getestet werden können.)etwas praktischer:
und Shertest-Version:
quelle
Ab Python3 können Sie verwenden
um zu überprüfen, ob die Liste leer ist
EDIT: Dies funktioniert auch mit Python2.7.
Ich bin mir nicht sicher, warum es so viele komplizierte Antworten gibt. Es ist ziemlich klar und unkompliziert
quelle
a
leer ist oder nicht.pythonic
a==[]
, wird true auf dem Python-Terminal gedruckt, wenn a leer ist. Andernfalls wird False ausgegeben. Sie können dies in einer if-Bedingung auch alsif(a==[])
Sie können sogar versuchen, bool () wie folgt zu verwenden
Ich liebe diese Art der Checkliste ist leer oder nicht.
Sehr praktisch und nützlich.
quelle
bool()
wird eine Python-Variable in einen Booleschen Wert konvertiert, sodass Sie die Wahrhaftigkeit oder Falschheit eines Werts speichern können , ohne eine if-Anweisung verwenden zu müssen. Ich denke, es ist weniger lesbar als nur eine Bedingung wie die akzeptierte Antwort zu verwenden, aber ich bin sicher, dass es andere gute Anwendungsfälle dafür gibt.Verwenden Sie einfach is_empty () oder machen Sie eine Funktion wie: -
Es kann für jede Datenstruktur wie eine Liste, Tupel, ein Wörterbuch und vieles mehr verwendet werden. Mit diesen können Sie es viele Male mit nur aufrufen
is_empty(any_structure)
.quelle
is_empty
deutet darauf hin, dass es etwas zurückgibt. Aber wenn es so wäre, wäre das einfach etwasbool(any_structure)
, das Sie stattdessen verwenden sollten ( wenn Sie überhaupt ein brauchenbool
).bool
, die (auch) Nachrichten in die Standardausgabe druckt?bool
. Du hast die Wahl. Ich schreibe beide, damit Sie zwischen ihnen wählen können.Ein einfacher Weg ist zu überprüfen, ob die Länge gleich Null ist.
quelle
Der Wahrheitswert einer leeren Liste ist,
False
während dies für eine nicht leere Liste der Fall istTrue
.quelle
Was mich hierher gebracht hat, ist ein spezieller Anwendungsfall: Ich wollte eigentlich eine Funktion , die mir sagt, ob eine Liste leer ist oder nicht. Ich wollte vermeiden, hier meine eigene Funktion zu schreiben oder einen Lambda-Ausdruck zu verwenden (weil es so schien, als ob es einfach genug sein sollte):
Und natürlich gibt es einen sehr natürlichen Weg, dies zu tun:
Natürlich müssen nicht verwendet werden
bool
inif
(dhif bool(L):
) , weil es impliziert wird . Aber für die Fälle, in denen "nicht leer" explizit als Funktion benötigt wird,bool
ist dies die beste Wahl.quelle
Hoffe das hilft.
quelle