Comment est-ce à lambda/rendement/générateur de compréhension du travail?
Je regardais à travers mon code aujourd'hui et trouvé ceci:
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')
)
)
)
Il semble prendre une dict de paramètres et de les transformer en une liste de paramètres à un shell de commande. Il semble que c'est à l'aide de rendement à l'intérieur d'un générateur de compréhension, j'ai pensé que ce serait impossible...?
>>> optionsToArgs({"x":1,"y":2,"z":3})
['-o', 'z=3', '-o', 'x=1', '-o', 'y=2']
Comment ça fonctionne?
- Dang. Parler de code illisible.
- le plus drôle, c'est la
list(reversed(list(
partie, pour obtenir le-o
commutateurs de droit, bien que - Aussi tous les lambdas pourraient avoir été juste
((lambda _: '-o')((yield x)) for x in kvs)
- ... et aussi l'instruction de retour pourrait être simplement exprimé en
[v for o in kvs for v in ["-o", o]]
. - Cela me rappelle de duffs appareil. À partir de ce jour ce sera à jamais connu comme les Chiens de l'appareil lol.
- Ressemble à quelqu'un a obtenu Maslow marteau et gardé frapper jusqu'à ce que ce sort.
- Lol l'homme pour ce projet, vous êtes mieux avec Lisp, je suppose aha ..
Vous devez vous connecter pour publier un commentaire.
Depuis Python 2.5,
yield <value>
est une expression, pas une déclaration. Voir PEP 342.Le code est affreusement et inutilement moche, mais c'est légal. Sa centrale astuce est d'utiliser
f((yield x))
à l'intérieur du générateur d'expression. Voici un exemple simple de la façon dont cela fonctionne:Fondamentalement, à l'aide de
yield
dans le générateur d'expression causes de produire deux valeurs pour chaque valeur de la source itératif. Comme le générateur d'expression parcourt la liste des chaînes, à chaque itération, layield x
premières récoltes d'une chaîne de la liste. L'expression de la cible de la genexp estf((yield x))
, donc pour chaque valeur de la liste, le "résultat" du générateur d'expression est la valeur def((yield x))
. Maisf
l'ignore son argument et renvoie toujours l'option de chaîne de"-o"
. Donc, à chaque étape, à travers le générateur, il donne d'abord la clé de la chaîne de valeur (par exemple,"x=1"
), puis"-o"
. L'extérieurlist(reversed(list(...)))
juste fait une liste de ce générateur, puis l'inverse, de sorte que le"-o"
s avant chaque option et non après.Cependant, il n'y a pas de raison de faire de cette façon. Il y a un certain nombre de beaucoup plus lisible des solutions de rechange. Peut-être le plus explicite est tout simplement:
Même si vous aimez laconique, "intelligent" de code, vous pouvez toujours faire
La
kvs
compréhension de liste elle-même est un mélange bizarre de tentative de lisibilité et illisibilité. Il est simplement écrit:Vous devriez envisager d'organiser une "intervention" pour celui qui le mettez dans votre base de code.
return list(itertools.chain(*[['-o', v] for v in kvs]))
. On ne sait pas pourquoi il a été changé de cette.itertools.chain.from_iterable
d'éviter d'utiliser le*
(qui peut devenir coûteux si la liste est grand)...Oh mon dieu. En gros, ça se résume à cela:
Donc quand itéré, thegenerator rendements
x
(un membre dekvs
) puis la valeur de retour def
, qui est toujours-o
, le tout dans une itération surkvs
. Quelle que soityield x
retourne et ce qui est transmis àf
est ignoré.Équivalents:
Il y a beaucoup de façons de le faire beaucoup plus simple, bien sûr. Même avec l'original de double-rendement truc, la chose entière aurait pu