Denken Sie an eine Funktion, die ich wegen ihrer Nebenwirkungen aufrufe, und geben Sie keine Werte zurück (z. B. Drucken auf dem Bildschirm, Aktualisieren der Benutzeroberfläche, Drucken in eine Datei usw.).
def fun_with_side_effects(x):
...side effects...
return y
Ist es nun pythonisch , Listenverständnisse zu verwenden, um diese Funktion aufzurufen:
[fun_with_side_effects(x) for x in y if (...conditions...)]
Beachten Sie, dass ich die Liste nirgendwo speichere
Oder sollte ich diese Funktion so nennen:
for x in y:
if (...conditions...):
fun_with_side_effects(x)
Was ist besser und warum?
python
list-comprehension
Sinan
quelle
quelle
for ... in
wird es in beiden Fällen verwendet - was zu Fragen wie dieser führt!Antworten:
Es ist sehr anti-pythonisch, dies zu tun, und jeder erfahrene Pythonista wird Ihnen die Hölle darüber geben. Die Zwischenliste wird nach ihrer Erstellung weggeworfen und kann möglicherweise sehr, sehr groß und daher teuer in der Erstellung sein.
quelle
for
, um den loszuwerdenif
).Sie sollten kein Listenverständnis verwenden , da dies, wie bereits erwähnt, eine große temporäre Liste erstellt, die Sie nicht benötigen. Die folgenden zwei Methoden sind äquivalent:
mit der Definition von
consume
aus deritertools
Manpage:Letzteres ist natürlich klarer und leichter zu verstehen.
quelle
map
möglicherweise nicht so intuitiv, wenn man noch keine funktionale Programmierung durchgeführt hat.consume = collections.deque(maxlen=0).extend
Listenverständnisse dienen zum Erstellen von Listen. Und wenn Sie keine Liste erstellen, sollten Sie kein Listenverständnis verwenden.
Also würde ich mich für die zweite Option entscheiden, einfach die Liste durchlaufen und dann die Funktion aufrufen, wenn die Bedingungen zutreffen.
quelle
Zweitens ist besser.
Denken Sie an die Person, die Ihren Code verstehen müsste. Mit dem ersten kannst du leicht schlechtes Karma bekommen :)
Sie können mit filter () zwischen den beiden wechseln. Betrachten Sie das Beispiel:
quelle
lambda x : x > 3
.for el in (x for x in y if x > 3):
.el
undx
kann den gleichen Namen haben, aber das könnte die Leute verwirren.Kommt auf dein Ziel an.
Wenn Sie versuchen, für jedes Objekt in einer Liste eine Operation auszuführen, sollte der zweite Ansatz angewendet werden.
Wenn Sie versuchen, eine Liste aus einer anderen Liste zu generieren, können Sie das Listenverständnis verwenden.
quelle
Du kannst tun
aber es ist nicht sehr hübsch.
quelle
Die Verwendung eines Listenverständnisses für seine Nebenwirkungen ist hässlich, nicht pythonisch, ineffizient, und ich würde es nicht tun. Ich würde
for
stattdessen eine Schleife verwenden, da einefor
Schleife einen prozeduralen Stil signalisiert, bei dem Nebenwirkungen wichtig sind.Wenn Sie jedoch unbedingt darauf bestehen, ein Listenverständnis für seine Nebenwirkungen zu verwenden, sollten Sie die Ineffizienz vermeiden, indem Sie stattdessen einen Generatorausdruck verwenden. Wenn Sie absolut auf diesem Stil bestehen, machen Sie einen der beiden folgenden Schritte:
oder:
Dies sind Generatorausdrücke, und sie generieren keine zufällige Liste, die weggeworfen wird. Ich denke, die
all
Form ist vielleicht etwas klarer, obwohl ich denke, dass beide verwirrend sind und nicht verwendet werden sollten.Ich finde das hässlich und würde es eigentlich nicht im Code machen. Aber wenn Sie darauf bestehen, Ihre Loops auf diese Weise zu implementieren, würde ich das so machen.
Ich neige dazu zu glauben, dass Listenverständnisse und deren Art einen Versuch signalisieren sollten, etwas zu verwenden, das zumindest schwach einem funktionalen Stil ähnelt. Wenn Sie Dinge mit Nebenwirkungen setzen, die diese Annahme brechen, müssen die Leute Ihren Code genauer lesen, und ich denke, das ist eine schlechte Sache.
quelle
fun_with_side_effects
True zurückgegeben wird?itertools.consume
existiert nicht mehr, wahrscheinlich weil es hässlich ist, Verständnis mit Nebenwirkungen zu verwenden.