Wie lokale variable in list comprehension?
Habe ich eine Methode, die eine Liste und ein Objekt zurück:
# input a list, returns an object
def map_to_obj(lst):
a_list = f(lst)
return a_list[0] if a_list else None
Ich möchte eine Liste, die alle zugeordneten Elemente, die nicht None
.
Wie diese:
v_list = [v1, v2, v3, v4]
[map_to_obj(v) for v in v_list if map_to_obj(v)]
Aber es scheint nicht gut zu nennen die map_to_obj
- Methode zweimal in der Liste erfassen.
Gibt es eine Möglichkeit, lokale Variablen in der Liste Verstehens, so dass Sie können haben eine bessere Leistung?
Oder weiß der compiler optimiert es automatisch?
Hier ist, was ich will:
(sml like)
[let mapped = map_to_obj(v) in for v in v_list if mapped end]
InformationsquelleAutor Hao Tan | 2014-10-31
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verschachtelte Liste Verständnis:
[x for x in [map_to_obj(v) for v in v_list] if x]
oder noch besser, eine Liste Verständnis um einen generator-Ausdruck:
[x for x in (map_to_obj(v) for v in v_list) if x]
map
undfilter
... ich' werde upvote, wie ich mochte es, wie Liegenden Hund übersetztfilter
in Bezug auf die l-c, aber die OP genehmigen dürfen, entweder eine von diesen Antworten, denn beide sind in Ordnung, nützlichen Antworten.lambda
lambda
(eigentlich die Python-Funktion implementiert, die das verstehen könnte-inline zu vermeiden, wird der Anruf overhead) beteiligt ist, ja, die listcomp gewinnt.map
/filter
gewinnen können, wenn die callback-Funktion ist eine C-built-in obwohl, wie Sie können, schieben Sie alle arbeiten auf der Schicht C, unter Umgehung der bytecode-interpreter-overhead, welcher listcomps nicht vermeiden können, wie Sie sind Python-level-Funktionen, nur mit direkter bytecode-Unterstützung für die append-to-list Schritt.lambda t: t is not None
mitNone.__ne__
, während die immer-so-etwas verrückt ist, wie es funktioniert (es gibtFalse
für andereNone
s, undNotImplemented
,, die passiert werden truthy, für alles andere), würde die Geschwindigkeit verbessern, dass die Lösung (in lokalen tests, diefilter
Arbeit sinkt um fast einen Faktor von 2), allerdings auf Kosten der Verständlichkeit.Einer Variablen Zuordnung ist nur eine einzelne Bindung:
Dies ist eine Allgemeine Antwort, und auch näher an dem, was Sie vorgeschlagen.
Also für Ihr problem, können Sie schreiben:
Können Sie vermeiden, re-Berechnung durch die Verwendung von python built-in
- filter
:map
gibt ein map Objekt ist keine Liste, undfilter
gibt ein filter-Objekt, so wird dies Kette die Funktionen, ohne dass intermediate-Listen.reduce
um die Arbeit zu tun?reduce
ist für die Kombination vieler Dinge nach unten, um eine Sache, nicht für die änderung viele Dinge zu viele Dinge. Die Arbeit erfolgt durch ein gekoppeltesmap
undfilter
(das ist dannlist
freundlich) entspricht, erfolgt durch eine listcomp führt, dass beide Filter-und mapping-Operationen.Ab
Python 3.8
, und die Einführung von bei der Zuordnung von Ausdrücken (PEP 572) (:=
operator), es ist möglich, eine lokale variable innerhalb einer Liste Verständnis, um zu vermeiden, ruft zweimal die gleiche Funktion:In unserem Fall, wir nennen können die Bewertung von
map_to_obj(v)
als variableo
während über das Ergebnis des Ausdrucks " um die Liste zu filtern; und so verwendeno
als der zugeordnete Wert:Einer lokalen variable kann eingestellt werden, in ein Verständnis von ein wenig geschummelt und mit einem extra " für " die "iteriert" durch eine 1-element-Tupel mit den gewünschten Wert für die lokale variable. Hier ist eine Lösung für die OP, das problem mit diesem Ansatz:
Hier
o
ist die lokale variable festgelegt wird gleichmap_to_obj(v)
für jedenv
.In meinen tests, diese ist etwas schneller als Liegender Hund verschachtelten generator Ausdrücke (und auch schneller als die OP ' s double-call zu
map_to_obj(v)
, was überraschend, kann schneller sein als das verschachtelte generator-Ausdruck, wenn diemap_to_obj
Funktion nicht zu langsam).Liste Verstehens sind in Ordnung für den einfachen Fällen, aber manchmal ist ein plain old
for
- Schleife ist die einfachste Lösung:Nun, wenn Sie wirklich wollen, eine Liste mit comp und nicht wollen, zu bauen eine tmp-Liste können Sie mit der iterator-Versionen
filter
undmap
:oder mehr einfach :
Den iterator Versionen nicht bauen eine temporäre Liste, die Sie verwenden, lazy evaluation.
Habe ich herausgefunden, ein Weg, mit
reduce
:Wie über die Leistung dieser?
timeit
Modul zu Zeit die verschiedenen Lösungen, aber deine obige snippet ist eine beliebig overcomplexificated Weg, um eine sehr einfache Sache - und ich bezweifle, dass es entweder schneller oder mehr Speicherplatz-effizienter als die gute alte for-Schleife oder die filter - /imap-Lösungen...f(lst)
Anrufe, aber das entfernen derNone
s die eine oder andere Weise ist unwahrscheinlich, dass das gesamte Bild verändern.reduce
wirklich nicht gefragt. Es ist für die Verringerung der Liste der Werte zu einem einzigen Wert (in der Regel eine Liste von skalaren zu einem einzigen Skalar), nicht die Umwandlung einer Liste in eine andere Liste.