Ich bin sicher, es gibt einen einfacheren Weg, der mir einfach nicht einfällt.
Ich rufe eine Reihe von Methoden auf, die eine Liste zurückgeben. Die Liste ist möglicherweise leer. Wenn die Liste nicht leer ist, möchte ich das erste Element zurückgeben. Andernfalls möchte ich None zurückgeben. Dieser Code funktioniert:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Es scheint mir, dass es eine einfache einzeilige Redewendung dafür geben sollte, aber für mein Leben kann ich nicht daran denken. Gibt es?
Bearbeiten:
Der Grund, warum ich hier nach einem einzeiligen Ausdruck suche, ist nicht, dass ich unglaublich knappen Code mag, sondern dass ich so viel Code schreiben muss:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
Was ich gerne tun würde, kann sicherlich mit einer Funktion erreicht werden (und wird es wahrscheinlich auch sein):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
Ich habe die Frage gestellt, weil ich häufig überrascht bin, was einfache Ausdrücke in Python bewirken können, und ich dachte, dass das Schreiben einer Funktion eine dumme Sache ist, wenn es einen einfachen Ausdruck gibt, der den Trick macht. Aber diese Antworten zu sehen, wie es scheint , eine Funktion ist die einfache Lösung.
quelle
next(iter(your_list), None)
anstatt davonfirst_item(your_list)
auszugehen, dass diesyour_list
nicht der Fall istNone
(get_first_list()
undget_second_list()
müssen immer eine iterierbare Datei zurückgeben).next(iter(your_list))
, denn wenn Sie ein zweites Argumentiter
angeben, sagen Sie, dass das erste Argument aufrufbar ist.None
hier ist der zweite Parameter fürnext()
, nichtiter()
.next()
Gibt den zweiten Parameter zurück, wenn er angegeben ist, anstatt ihn zu erhöhen,StopIteration
wenn eryour_list
leer ist.Antworten:
Python 2.6+
Wenn
your_list
kann seinNone
:Python 2.4
Beispiel:
Eine andere Möglichkeit besteht darin, die obige Funktion zu integrieren:
Um dies zu vermeiden
break
, könnten Sie schreiben:Wo:
quelle
""
in der Liste haben, wird diese verworfen und durch eine leere Liste ersetzt[]
. Wenn Sie eine 0 haben, wird diese auch durch ersetzt[]
. Wenn SieFalse
dort drin haben , auch ersetzt. In einem bestimmten Fall könnten Sie damit durchkommen, aber es ist eine schlechte Angewohnheit, sich zu entwickeln.bool(lst)
sagt uns, oblen(lst) > 0
es uns nichts darüber sagt, was Elementelst
enthalten, z. B.bool([False]) == True;
der Ausdruck wird[False] or []
zurückgegeben[False]
, das gleiche gilt für die[0] or []
Rückgabe[0]
.yield_first()
, umbreak
Aussage zu vermeiden .Der beste Weg ist folgender:
Sie können es auch in einer Zeile tun, aber für den Programmierer ist es viel schwieriger zu lesen:
quelle
next(iter(your_list), None)
next(iter(your_list))
ausreichendNone
OP- Aufforderung zurückzukehren . Versuchen Sie :next(iter([]))
.Das sollte funktionieren.
Übrigens habe ich die Variable nicht verwendet
list
, da dies die eingebautelist()
Funktion überschreibt .Edit: Ich hatte hier früher eine etwas einfachere, aber falsche Version.
quelle
Die pythonischste Art ist die Verwendung von next () für einen Iterator, da die Liste iterierbar ist . Genau wie das, was @JFSebastian am 13. Dezember 2011 in den Kommentar aufgenommen hat.
next(iter(the_list), None)
Dies gibt None zurück, wennthe_list
es leer ist. siehe next () Python 2.6+oder wenn Sie sicher wissen,
the_list
ist nicht leer:iter(the_list).next()
siehe iterator.next () Python 2.2+quelle
return l[0] if l else None
z. B. wenn die Liste eine libcomp war. Wenn die Liste tatsächlich ein Genexpr ist, ist dies sogar noch besser, da Sie nicht die gesamte Liste wie innext(iter(x for x in range(10) if x % 2 == 0), None)
the_list
es nicht leer ist, würden Sie schreibenthe_list[0]
.Wenn Sie versuchen, das Erste (oder Keine) aus einem Listenverständnis herauszuholen, können Sie zu einem Generator wechseln, um Folgendes zu tun:
Pro: Funktioniert, wenn bla nicht indizierbar ist. Con: Es ist eine ungewohnte Syntax. Es ist jedoch nützlich, wenn Sie in ipython herumhacken und Dinge filtern.
quelle
Die Lösung des OP ist fast da, es gibt nur ein paar Dinge, die es pythonischer machen.
Zum einen ist es nicht erforderlich, die Länge der Liste zu ermitteln. Leere Listen in Python werden bei einer if-Prüfung als falsch ausgewertet. Sag es einfach
Darüber hinaus ist es eine sehr schlechte Idee, Variablen zuzuweisen, die sich mit reservierten Wörtern überschneiden. "Liste" ist ein reserviertes Wort in Python.
Ändern wir das also in
Ein wirklich wichtiger Punkt, den viele Lösungen hier übersehen, ist, dass alle Python-Funktionen / -Methoden standardmäßig None zurückgeben . Versuchen Sie Folgendes unten.
Sofern Sie None nicht zurückgeben müssen, um eine Funktion vorzeitig zu beenden, ist es nicht erforderlich, None explizit zurückzugeben. Kurz gesagt, geben Sie einfach den ersten Eintrag zurück, falls vorhanden.
Und schließlich wurde dies vielleicht impliziert, aber nur um explizit zu sein (weil explizit besser als implizit ist ), sollte Ihre Funktion die Liste nicht von einer anderen Funktion abrufen. Übergeben Sie es einfach als Parameter. Das Endergebnis wäre also
Wie gesagt, das OP war fast da und nur ein paar Berührungen verleihen ihm den Python-Geschmack, den Sie suchen.
quelle
get_first_item
sollte einendefault
Parameter (wiedict.get
) akzeptieren, der standardmäßig None ist. Somit kommuniziert die Funktionsschnittstelle explizit, was passiert, wenn siemy_list
leer ist.quelle
Ehrlich gesagt glaube ich nicht, dass es eine bessere Redewendung gibt: Ihre ist klar und knapp - Sie brauchen nichts "Besseres". Vielleicht, aber das ist wirklich eine Frage des Geschmacks ist, könnten Sie verändern
if len(list) > 0:
mitif list:
- einer leeren Liste wird immer auf False auswerten.In einem ähnlichen Zusammenhang ist Python nicht Perl (kein Wortspiel beabsichtigt!), Sie müssen nicht den coolsten Code bekommen, der möglich ist.
Eigentlich war der schlechteste Code, den ich in Python gesehen habe, auch sehr cool :-) und völlig unbrauchbar.
Übrigens berücksichtigen die meisten Lösungen, die ich hier gesehen habe, nicht, wenn list [0] als False ausgewertet wird (z. B. leere Zeichenfolge oder Null). In diesem Fall geben alle None und nicht das richtige Element zurück.
quelle
if lst:
als zu schreibenif len(lst) > 0:
. Verwenden Sie auch keine Python-Schlüsselwörter als Variablennamen. es endet in Tränen. Es ist üblich,L
oderlst
als Variablenname für eine Liste zu verwenden. Ich bin sicher, in diesem Fall wollten Sie nicht vorschlagen, tatsächlichlist
als Variablennamen zu verwenden, sondern nur "eine Liste". Und +1 für "wenn lst [0] zu False ausgewertet wird".Der pythonischste Ansatz ist der, der in der am besten bewerteten Antwort gezeigt wurde, und es war das erste, was mir beim Lesen der Frage in den Sinn kam. So verwenden Sie es zuerst, wenn die möglicherweise leere Liste an eine Funktion übergeben wird:
Und wenn die Liste von einer
get_list
Funktion zurückgegeben wird:Andere Möglichkeiten, dies zu tun, wurden hier anhand von Erklärungen demonstriert
for
Als ich anfing, über clevere Wege nachzudenken, war dies das zweite, woran ich dachte:
Dies setzt voraus, dass die Funktion hier endet und implizit zurückgibt,
None
wennget_list
eine leere Liste zurückgegeben wird. Der folgende explizite Code ist genau gleichwertig:if some_list
Das Folgende wurde ebenfalls vorgeschlagen (ich habe den falschen Variablennamen korrigiert), wobei auch das Implizite verwendet wird
None
. Dies wäre dem oben genannten vorzuziehen, da die logische Prüfung anstelle einer möglicherweise nicht stattfindenden Iteration verwendet wird. Dies sollte sofort leichter zu verstehen sein, was passiert. Wenn wir jedoch aus Gründen der Lesbarkeit und Wartbarkeit schreiben, sollten wirreturn None
am Ende auch das Explizite hinzufügen :Slice
or [None]
und wählen Sie den nullten IndexDieser ist auch in der am besten bewerteten Antwort:
Das Slice ist nicht erforderlich und erstellt eine zusätzliche Liste mit einem Element im Speicher. Das Folgende sollte performanter sein. Um zu erklären,
or
gibt das zweite Element , wenn die erste ist ,False
in einem booleschen Kontext, also wennget_list
eine leere Liste zurückgegeben, der Ausdruck in den Klammern enthalten eine Liste mit ‚Keine‘ zurück, die dann durch den zugegriffen werden0
Index:Der nächste verwendet die Tatsache, dass und das zweite Element zurückgibt, wenn sich das erste
True
in einem booleschen Kontext befindet. Da es zweimal auf my_list verweist, ist es nicht besser als der ternäre Ausdruck (und technisch gesehen kein Einzeiler):next
Dann haben wir den folgenden cleveren Einsatz des eingebauten
next
unditer
Gibt zur Erklärung
iter
einen Iterator mit einer.next
Methode zurück. (.__next__
in Python 3.) Dannnext
ruft das eingebaute diese.next
Methode auf, und wenn der Iterator erschöpft ist, gibt es den von uns angegebenen Standard zurück.None
.redundanter ternärer Ausdruck (
a if b else c
) und ZurückkreisenDas Folgende wurde vorgeschlagen, aber das Umgekehrte wäre vorzuziehen, da die Logik normalerweise besser im Positiven als im Negativen verstanden wird. Da
get_list
zweimal aufgerufen wird, würde das Ergebnis schlecht funktionieren, es sei denn, das Ergebnis wird auf irgendeine Weise gespeichert.Das bessere Gegenteil:
Verwenden Sie noch besser eine lokale Variable, die
get_list
nur einmal aufgerufen wird, und Sie haben die empfohlene Pythonic-Lösung zuerst besprochen:quelle
In Bezug auf Idiome gibt es ein itertools Rezept genannt
nth
.Aus itertools Rezepten:
Wenn Sie Einzeiler möchten, sollten Sie eine Bibliothek installieren, die dieses Rezept für Sie implementiert, z
more_itertools
.Es steht ein weiteres Tool zur Verfügung, das nur das erste aufgerufene Element zurückgibt
more_itertools.first
.Diese itertools werden generisch für alle iterierbaren Elemente skaliert, nicht nur für Listen.
quelle
my_list[0] if len(my_list) else None
quelle
len
ohne Grund. Wenn Sie es löschen würden, würde der obige Code dasselbe tun.Aus Neugier habe ich zwei der Lösungen zeitlich festgelegt. Die Lösung, die eine return-Anweisung verwendet, um eine for-Schleife vorzeitig zu beenden, ist auf meinem Computer mit Python 2.5.1 etwas teurer. Ich vermute, dies hat mit dem Einrichten der Iterable zu tun.
Dies sind die Timings, die ich bekommen habe:
quelle
quelle
if len(a) > 0:
aber dies wird als guter Stil angesehen. Beachten Sie, wie gut dies das Problem ausdrückt: "Versuchen Sie, den Kopf einer Liste zu extrahieren, und kehren Sie zurück, wenn dies nicht funktioniert.None
" Google-Suche nach "EAFP" oder schauen Sie hier: python.net/~goodger/projects/pycon/2007/idiomatic/…Übrigens: Ich würde Ihren allgemeinen Programmablauf in etwa so überarbeiten:
(Vermeiden Sie Wiederholungen, wann immer dies möglich ist.)
quelle
Wie wäre es damit:
(my_list and my_list[0]) or None
Hinweis: Dies sollte für Objektlisten gut funktionieren, kann jedoch bei einer Nummern- oder Zeichenfolgenliste gemäß den folgenden Kommentaren zu einer falschen Antwort führen.
quelle
([0,1] and 0) or None
!(['','A'] and '') or None
.my_list[0]
als ausgewertet wirdFalse
, sollte das Ergebnis seinNone
.my_list[0] if len(my_list) else None
Ich bin mir nicht sicher, wie pythonisch das ist, aber bis es eine erste Funktion in der Bibliothek gibt, füge ich dies in die Quelle ein:
Es ist nur eine Zeile (entspricht Schwarz) und vermeidet Abhängigkeiten.
quelle
Verwenden des and-or-Tricks:
quelle
Wahrscheinlich nicht die schnellste Lösung, aber niemand erwähnte diese Option:
Wenn Sie zurückkehren können,
get_list()
könnenNone
Sie Folgendes verwenden:Vorteile:
-eine Linie
-Du rufst nur
get_list()
einmal an-einfach zu verstehen
quelle
Mein Anwendungsfall bestand nur darin, den Wert einer lokalen Variablen festzulegen.
Persönlich fand ich den Versuch und außer Stilreiniger zu lesen
als eine Liste zu schneiden.
quelle
Einige Leute haben vorgeschlagen, so etwas zu tun:
Das funktioniert in vielen Fällen, aber es funktioniert nur, wenn list [0] nicht gleich 0, False oder einer leeren Zeichenfolge ist. Wenn list [0] 0, False oder eine leere Zeichenfolge ist, gibt die Methode fälschlicherweise None zurück.
quelle
Sie können die Extraktionsmethode verwenden . Mit anderen Worten, extrahieren Sie diesen Code in eine Methode, die Sie dann aufrufen würden.
Ich würde nicht versuchen, es viel mehr zu komprimieren, die Einzeiler scheinen schwerer zu lesen als die ausführliche Version. Und wenn Sie die Extraktionsmethode verwenden, ist es ein Einzeiler;)
quelle
quelle
ist nicht die idiomatische Python, die ternären Operatoren im C-Stil entspricht
dh.
quelle