Anwendungsfall für verschachtelte / mehrere Listenkomprehensionen oder Generator Ausdrücke. Wann ist es eleganter?

StackOverflow https://stackoverflow.com/questions/648675

Frage

Ich sehe diese Art der Sache manchmal:

(k for k in (j for j in (i for i in xrange(10))))

Jetzt das wirklich mein Gehirn beugt, und ich würde lieber war es nicht auf diese Weise dargestellt.

Gibt es Anwendungsfälle oder Beispiele für diese verschachtelten Ausdrücke verwendet zu haben, wo es elegantere war und besser lesbar als wenn es sich um eine verschachtelte Schleife gewesen war?

Edit: Vielen Dank für die Beispiele von Möglichkeiten, dies zu vereinfachen. Es ist nicht wirklich, was ich gefragt, ich habe mich gefragt, ob es irgendwelche Zeiten, als es elegant war.

War es hilfreich?

Lösung

Überprüfen Sie PEP 202 , die in dem Listenkomprehensionen Syntax war, auf die eingeführte Sprache.

Ihr Beispiel für das Verständnis, gibt es eine einfache Regel von Guido selbst:

  • Die Form [... für x ... für y ...] Nester, mit dem letzten Index   schnellste variierend, genau wie für Schleifen verschachtelt sind.

Auch von PEP 202, die Ihre Frage zu beantworten dienen:

Rationale
    List comprehensions provide a more concise way to create lists in
    situations where map() and filter() and/or nested loops would
    currently be used.

Wenn Sie eine Situation wie die hätten, könnten Sie finden es elegant sein. IMHO, obwohl, können mehrere verschachtelte Liste Comprehensions weniger klar im Code als verschachtelte for-Schleifen, da for Schleifen leicht visuell analysiert werden.

Andere Tipps

Wenn Sie sich Sorgen über zu viel Komplexität sind auf einer Linie, man könnte es aufgeteilt:

(k for k in 
    (j for j in 
        (i for i in xrange(10))))

Ich habe immer Linie Fortsetzungen fand ein wenig seltsam in Python zu sehen, aber das macht es leichter zu sehen, was jeder ist Looping über. Da eine zusätzliche Zuweisung / Lookup wird nichts gehen zu machen oder zu brechen, könnte man es auch so schreiben:

gen1 = (i for i in xrange(10))
gen2 = (j for j in gen1)
gen3 = (k for k in gen2)

In der Praxis, ich glaube nicht, dass ich jemals ein Verständnis mehr als 2-tief verschachtelt habe, und an diesem Punkt war es noch recht einfach zu verstehen.

Im Fall von Ihrem Beispiel, würde ich wahrscheinlich schreiben Sie es als:

foos = (i for i in xrange(10))
bars = (j for j in foos)
bazs = (k for k in bars)

Da aussagekräftigeren Namen, ich denke, das wahrscheinlich ganz klar wäre, und ich kann dort nicht vorstellen jede messbare Leistungsdifferenz zu sein.

Vielleicht denken Sie jetzt mehr von Ausdrücken wie:

(x for x in xs for xs in ys for ys in lst)

- tatsächlich, das ist nicht einmal gültig. Sie haben, um die Dinge in der anderen Reihenfolge zu setzen:

(x for ys in lst for xs in ys for x in xs)

Ich könnte das als eine schnelle Art und Weise schreibe eine Liste der Abflachung, aber im Allgemeinen Ich glaube, du bist schreiben:. Die Zeit, die Sie durch weniger Eingabe speichern ist in der Regel ausgeglichen Sie durch die zusätzliche Zeit verbringen Recht, den Generator Ausdruck bekommen

Da sie Generator Ausdrücke sind, können Sie binden jeweils an seinen eigenen Namen ohne jede Änderung in der Leistung es besser lesbar zu machen. Ändert es zu einer verschachtelten Schleife würde, um die Leistung wahrscheinlich schädlich sein.

irange = (i for i in xrange(10))
jrange = (j for j in irange)
krange = (k for k in jrange)

Es ist wirklich egal, was Sie sich entscheiden, ich denke, das mehrzeiligen Beispiel besser lesbar ist, im Allgemeinen.

Caveat. Eleganz ist zum Teil eine Frage des Geschmacks

Liste Comprehensions sind nie mehr klar als die for-Schleife erweitert entspricht. Für Schleifen sind auch mächtig als Listenkomprehensionen. Also, warum sie überhaupt benutzen?

Welche Listenkomprehensionen sind, ist prägnante -. Sie ermöglichen es Ihnen etwas in einer einzigen Zeile zu tun

Die Zeit, um eine Liste Verständnis zu verwenden, wenn Sie eine bestimmte Liste benötigen, kann es on the fly ziemlich leicht erstellt werden, und Sie wollen nicht, oder Zwischen Objekte benötigen rumhängen. Dies könnte passieren, wenn man einige Objekte in dem aktuellen Bereich zu einem einzigen Objekt verpacken muß, die Sie in eine Funktion ernähren können, wie unten:

list1 = ['foo', 'bar']
list2 = ['-ness', '-ity']
return filterRealWords([str1+str2 for str1 in list1 for str2 in list2])

Dieser Code ist in etwa so lesbar als die erweiterte Version, aber es ist viel kürzer. Es vermeidet die Schaffung / ein Objekt zu benennen, die nur einmal im aktuellen Bereich verwendet wird, der wohl eleganter ist.

Der Ausdruck:

(k for k in (j for j in (i for i in xrange(10))))

entspricht:

(i for i in xrange(10))

das ist fast das gleiche:

xrange(10)

Die letzte Variante ist eleganter als die erste.

Ich finde es kann in Situationen wie diese sinnvoll und elegant sein, wo Sie Code wie folgt aussehen:

output = []
for item in list:
    if item >= 1:
        new = item += 1
        output.append(new)

Sie können es machen einen Einzeiler wie folgt aus:

output = [item += 1 for item in list if item >= 1]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top