455 Stimmen

Python-Idiom zur Rückgabe des ersten Elements oder None

Ich rufe eine Reihe von Methoden auf, die eine Liste zurückgeben. Die Liste kann leer sein. Wenn die Liste nicht leer ist, möchte ich das erste Element zurückgeben; andernfalls möchte ich None . Dieser Code funktioniert:

def main():
    my_list = get_list()
    if len(my_list) > 0:
        return my_list[0]
    return None

aber es scheint mir, dass es ein einfaches einzeiliges Idiom für diese Aufgabe geben sollte. Gibt es das?

391voto

jfs Punkte 370717

Python 2.6+

next(iter(your_list), None)

Si your_list kann sein None :

next(iter(your_list or []), None)

Python 2.4

def get_first(iterable, default=None):
    if iterable:
        for item in iterable:
            return item
    return default

x = get_first(get_first_list())
if x:
    ...
y = get_first(get_second_list())
if y:
    ...

Eine andere Möglichkeit besteht darin, die obige Funktion einzubinden:

for x in get_first_list() or []:
    # process x
    break # process at most one item
for y in get_second_list() or []:
    # process y
    break

Zur Vermeidung von break könnten Sie schreiben:

for x in yield_first(get_first_list()):
    x # process x
for y in yield_first(get_second_list()):
    y # process y

Wo:

def yield_first(iterable):
    for item in iterable or []:
        yield item
        return

292voto

efotinis Punkte 13896

Der beste Weg ist dieser:

a = get_list()
return a[0] if a else None

Man könnte es auch in einer Zeile machen, aber das ist für den Programmierer viel schwieriger zu lesen:

return (get_list()[:1] or [None])[0]

110voto

recursive Punkte 80517
(get_list() or [None])[0]

Das sollte funktionieren.

Übrigens habe ich die Variable nicht verwendet list denn das überschreibt das eingebaute list() Funktion.

Edit: Ich hatte vorhin eine etwas einfachere, aber falsche Version hier.

38voto

Devy Punkte 9035

Der idiomatischste Weg in Python ist die Verwendung von next() für einen Iterator, da list iterierbar . genau wie das, was @J.F.Sebastian in seinem Kommentar vom 13. Dezember 2011 schrieb.

next(iter(the_list), None) Dies gibt None zurück, wenn the_list leer ist. siehe next() Python 2.6+

oder wenn Sie ganz sicher wissen the_list nicht leer ist:

iter(the_list).next() siehe iterator.next() Python 2.2+

19voto

Python Idiom zu ersten Element oder None zurückgeben?

Der pythonische Ansatz ist das, was die am meisten hochgestimmte Antwort gezeigt hat, und es war das erste, was mir in den Sinn kam, als ich die Frage las. Hier ist, wie es zu verwenden, zunächst wenn die möglicherweise leere Liste in eine Funktion übergeben wird:

def get_first(l): 
    return l[0] if l else None

Und wenn die Liste von einer get_list función:

l = get_list()
return l[0] if l else None

Neu in Python 3.8, Zuweisungsausdrücke

Zuweisungsausdrücke verwenden den In-Place-Zuweisungsoperator (informell Walross-Operator genannt), := , neu in Python 3.8, erlaubt es uns, die Prüfung und Zuweisung an Ort und Stelle durchzuführen, was den Einzeiler ermöglicht:

return l[0] if (l := get_list()) else None

Als langjähriger Python-Benutzer fühlt sich dies an, als ob wir versuchen, zu viel auf einer Zeile zu tun - ich denke, es wäre besser, die vermutlich ebenso leistungsfähig zu tun:

if l := get_list():
    return l[0]
return None

Unterstützt wird diese Formulierung durch Tim Peters Aufsatz im PEP, in dem diese Änderung der Sprache vorgeschlagen wird. Auf die erste Formulierung ist er nicht eingegangen, aber aufgrund der anderen Formulierungen, die ihm gefallen haben, glaube ich nicht, dass er etwas dagegen hätte.

Andere Möglichkeiten, die hier gezeigt werden, mit Erklärungen

for

Als ich anfing, über clevere Möglichkeiten nachzudenken, kam mir dies als Zweites in den Sinn:

for item in get_list():
    return item

Dies setzt voraus, dass die Funktion hier endet und implizit zurückkehrt None si get_list gibt eine leere Liste zurück. Der folgende explizite Code ist genau gleichwertig:

for item in get_list():
    return item
return None

if some_list

Es wurde auch folgendes vorgeschlagen (ich habe den falschen Variablennamen korrigiert), das ebenfalls die implizite None . Dies wäre der obigen Lösung vorzuziehen, da sie die logische Prüfung anstelle einer Iteration verwendet, die möglicherweise nicht stattfindet. Dies sollte einfacher sein, sofort zu verstehen, was passiert. Aber wenn wir für die Lesbarkeit und Wartbarkeit schreiben, sollten wir auch die explizite return None am Ende:

some_list = get_list()
if some_list:
    return some_list[0]

slice or [None] und wählen Sie den nullten Index

Dies ist auch die Antwort, die am häufigsten hochgestuft wurde:

return (get_list()[:1] or [None])[0]

Der Slice ist unnötig und erzeugt eine zusätzliche Ein-Element-Liste im Speicher. Das Folgende sollte leistungsfähiger sein. Zur Erläuterung, or gibt das zweite Element zurück, wenn das erste Element False in einem booleschen Kontext, wenn also get_list eine leere Liste zurückgibt, gibt der in den Klammern enthaltene Ausdruck eine Liste mit dem Wert "None" zurück, auf die dann mit dem Befehl 0 Index:

return (get_list() or [None])[0]

Der nächste nutzt die Tatsache, dass und gibt das zweite Element, wenn das erste ist True in einem booleschen Kontext, und da er zweimal auf my_list verweist, ist er nicht besser als der ternäre Ausdruck (und technisch gesehen kein Einzeiler):

my_list = get_list() 
return (my_list and my_list[0]) or None

next

Dann haben wir die folgende clevere Verwendung des eingebauten next y iter

return next(iter(get_list()), None)

Zur Erklärung, iter gibt einen Iterator mit einer .next Methode. ( .__next__ in Python 3). Dann wird das eingebaute next Anrufe, die .next Methode und gibt, wenn der Iterator erschöpft ist, den von uns angegebenen Standardwert zurück, None .

redundanter ternärer Ausdruck ( a if b else c ) und zurückfahren

Vorgeschlagen wurde das Folgende, doch wäre die Umkehrung vorzuziehen, da Logik in der Regel besser im positiven als im negativen Sinne verstanden wird. Da get_list zweimal aufgerufen wird, würde dies schlecht funktionieren, es sei denn, das Ergebnis wird auf irgendeine Art und Weise zwischengespeichert:

return None if not get_list() else get_list()[0]

Die bessere Umkehrung:

return get_list()[0] if get_list() else None

Noch besser ist es, eine lokale Variable zu verwenden, so dass get_list wird nur einmal aufgerufen, und Sie haben die empfohlene Pythonic-Lösung, die zuerst besprochen wurde:

l = get_list()
return l[0] if l else None

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X