Packaged
-> hachibeeDI / letexpr
Es ist eine Geschichte
Staatsmonade in Python Ich habe diesen Artikel geschrieben und wollte einen let-Ausdruck wie Haskell in Python, also habe ich darüber nachgedacht.
Dann im entsprechenden Beitrag Machen wir eine einzeilige Programmierung Weil es so etwas gab, werde ich dafür sorgen, dass es sich gut anfühlt, es umzuleiten. Ich dachte, aber ich gab die Ablenkung auf, weil es so aussieht, als würde ich mich bewerben. Also werde ich mein Bestes geben.
Der let-Ausdruck scheint innerhalb des let zu binden und den Ausdruck mit in auszuwerten. Es scheint auch, dass die in let gebundenen Variablen aus dem gesamten let-Ausdruck referenziert werden können.
Lassen Sie uns das Ergebnis vorerst an eine Variable binden, damit es in verwendet werden kann
class let(object):
def __init__(self, action=None):
if action is None:
name, act = action
self.lets = {name: act()}
else:
self.lets = {}
def __or__(self, action):
''' :type action: (str, func) '''
name, f = action
self.lets[name] = f()
return self
def in_(self, func):
return func(**self.lets)
if __name__ == '__main__':
x = let(('xx', lambda : 1 + 2)) | ('y', lambda : 'yyy') | ('z', lambda : 5)
print x.in_(lambda xx, y, z: str(xx) + y + str(z))
Es wurde vorerst eine Form. Es ist jedoch nicht möglich, auf den Wert zwischen let-Ausdrücken zu verweisen, daher werde ich dafür sorgen, dass es sich gut anfühlt.
Wie oben erwähnt, können Sie in Python einen Wert an das Argument übergeben, das dem Schlüssel entspricht, indem Sie dem Argument der Funktion ein "** Wörterbuch" übergeben, im Gegensatz zu einigen gängigen Sprachen usw. Ein Fehler wird wegen Überschuss oder Mangel ausgegeben. Mit anderen Worten, Sie müssen nur die Werte übergeben, die jeder in den in "self.lets_" gespeicherten Ergebnissen benötigt.
In einem solchen Fall ist das Modul "inspect" praktisch. Verwenden Sie daher die Funktion "getargspec", um nur die erforderlichen Argumente zu übergeben.
from inspect import getargspec
class let(object):
def __init__(self, action=None):
if action is not None:
name, act = action
self.lets = {name: act()}
else:
self.lets = {}
def __or__(self, action):
''' :type action: (str, func) '''
name, f = action
require_arg_keys = getargspec(f).args
self.lets[name] = f(
**self.__extract_require_args(require_arg_keys)
)
return self
def __extract_require_args(self, arg_keys):
return {k: v for k, v in self.lets.iteritems() if k in arg_keys}
def in_(self, func):
require_arg_keys = getargspec(func).args
return func(
**self.__extract_require_args(require_arg_keys)
)
Versuchen wir nun, einen Ausdruck zu übergeben, für den tatsächlich verschiedene Argumente erforderlich sind. Lassen Sie uns den Einzug cool machen.
measure = \
(let()
| ('x', lambda : 10)
| ('y', lambda : 20)
| ('size', lambda x, y: x * y)
| ('hoge', lambda x, y: 'fooo')
) \
.in_(lambda x, y, size:
'x = {x}, y = {y}, x * y = {size}'.format(x=x, y=y, size=size))
print measure # => x = 10, y = 20, x * y = 200
Du hast es getan, nicht wahr? In der aktuellen Situation bewerten wir von oben nach unten, sodass wir den oberen Wert nicht vom unteren Lambda erhalten können. Wenn wir jedoch unser Bestes tun, um die Bewertung des Ausdrucks zu verzögern, können wir dies auch tun. Genau. Ich dachte, normal ist das Beste, weil derjenige, der es normal geschrieben hat, es normal lesen kann.
Recommended Posts