Wie funktioniert dieses Lambda / Ertrag / Generator-Verständnis?
Ich war auf der Suche durch meine codebase heute und fand diese:
def optionsToArgs(options, separator='='):
kvs = [
(
"%(option)s%(separator)s%(value)s" %
{'option' : str(k), 'separator' : separator, 'value' : str(v)}
) for k, v in options.items()
]
return list(
reversed(
list(
(lambda l, t:
(lambda f:
(f((yield x)) for x in l)
)(lambda _: t)
)(kvs, '-o')
)
)
)
Es scheint eine dict-Parameter, und schalten Sie Sie in eine Liste von Parametern für ein shell-Befehl. Wie es aussieht ist es mit der Ausbeute im inneren eine generator-comprehension, ich dachte, das wäre unmöglich...?
>>> optionsToArgs({"x":1,"y":2,"z":3})
['-o', 'z=3', '-o', 'x=1', '-o', 'y=2']
Wie funktioniert es?
Kommentar zu dem Problem
Dang. Sprechen Sie über die nicht lesbare code.
der lustigste Teil ist der
- Liste(reversed(list(
- Teil zu Holen Sie sich die -o
Schalter rechts, obwohl Auch alle lambdas haben könnte, wurden nur
((lambda _: '-o')((Ertrag x)) für x kvs)
... und auch die return-Anweisung konnte nur werden, ausgedrückt als
[v, für o-kvs-v in ["-o", o]]
. Das erinnert mich an duffs device. Von diesem Tag an wird für immer bekannt sein als Hunde Gerät, lol.
InformationsquelleAutor der Frage Dog | 2013-04-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Seit Python 2.5,
yield <value>
ist ein Ausdruck, keine Anweisung. Sehen PEP 342.Der code ist furchtbar und unnötig hässlich, aber es ist legal. Seine zentrale trick besteht darin, mit
f((yield x))
im inneren des Generators-Ausdruck. Hier ein einfacheres Beispiel, wie das funktioniert:Grundsätzlich mit
yield
im generator-Ausdruck bewirkt, dass es erzeugen zwei Werte für jeden Wert in der Quelle durchsuchbar. Als der generator-Ausdruck iteriert über die Liste der Zeichenfolgen, die bei jeder iteration, dieyield x
erste liefert einen string aus der Liste. Die target-expression der genexp istf((yield x))
, so wird für jeden Wert in der Liste, das "Ergebnis" des generator-Ausdrucks ist der Wert vonf((yield x))
. Aberf
einfach ignoriert argument und gibt immer die option string"-o"
. So auf jedem Schritt durch den generator liefert es erste Schlüssel-Wert-string (z.B."x=1"
), dann"-o"
. Die äußerenlist(reversed(list(...)))
macht einfach eine Liste von diesen generator und dann kehrt es um, so dass die"-o"
s kommen vor jeder option nicht nach.Jedoch, es gibt keinen Grund, es zu tun auf diese Weise. Es gibt eine Reihe von viel mehr lesbare alternativen. Vielleicht expliziteste ist einfach:
Selbst wenn man, wie knapp, "clever" - code, Sie konnten gerade noch tun
Den
kvs
Liste das Verständnis selbst ist eine bizarre Mischung aus versucht, die Lesbarkeit und unlesbarkeit. Es ist einfach geschrieben:Sollten Sie erwägen, die Anordnung einer "intervention", denn wer diese in Ihrer Codebasis.
InformationsquelleAutor der Antwort BrenBarn
Oh Gott. Im Grunde läuft es auf diese:
Also bei der Iteration thegenerator Erträge
x
(Mitgliedkvs
) und dann die return-Wertf
, das ist immer-o
alle in einer iteration überkvs
. Wasyield x
gibt und was wird übergebenf
ignoriert.Entsprechungen:
Gibt es viele Möglichkeiten, dies zu tun viel einfacher, natürlich. Sogar mit der original double-yield-trick, die ganze Sache könnte habe
InformationsquelleAutor der Antwort Pavel Anossov