Pythonで関数のインライン定義、または複数行のラムダを許可するための最良のレシピを探しています。
たとえば、次のことをしたいと思います。
def callfunc(func):
func("Hello")
>>> callfunc(define('x', '''
... print x, "World!"
... '''))
Hello World!
この回答define
で関数の例を見つけました:
def define(arglist, body):
g = {}
exec("def anonfunc({0}):\n{1}".format(
arglist,
"\n".join(" {0}".format(line) for line in body.splitlines())), g)
return g["anonfunc"]
これは可能な解決策の 1 つですが、理想的ではありません。望ましい機能は次のとおりです。
- インデントをより賢くし、
anonfunc
内部をより適切に非表示にします (たとえば、関数のスコープに含めないでください)。- 周囲のスコープ/キャプチャ内の変数へのアクセスを提供します
- より良いエラー処理
そして、私が考えていなかったいくつかのこと。上記のほとんどを行った非常に優れた実装がありましたが、残念ながら負けました。誰かが似たようなものを作っていないか気になります。
免責事項:
これが Python ユーザーの間で物議をかもしており、ハックまたは非 Pythonic と見なされていることは十分承知しています。また、python-dev メーリング リストで複数行のラムダに関する議論があり、同様の機能が意図的に省略されていることも認識しています。しかし、同じ議論から、他の多くの人々もそのような機能に関心を持っていることを知りました。
私はこれが良いアイデアかどうかを尋ねているわけではありませんが、代わりに:これを実装することに決めた場合 (楽しさと好奇心、狂気、純粋にこれが良いアイデアだと考えているか、銃を突きつけられているかのいずれか) python (2.7 または 3.x) の現在の機能を使用して、匿名のdefine
作業を可能な限り近づけるにはどうすればよいですか?def
例:
理由についてもう少し説明すると、これは GUI でのコールバックに非常に便利です。
# gtk example:
self.ntimes = 0
button.connect('clicked', define('*a', '''
self.ntimes += 1
label.set_text("Button has been clicked %d times" % self.ntimes)
''')
関数を で定義することの利点def
は、コードがより論理的な順序になっていることです。これは Twisted アプリケーションから取った単純化されたコードです:
# twisted example:
def sayHello(self):
d = self.callRemote(HelloCommand)
def handle_response(response):
# do something, this happens after (x)!
pass
d.addCallback(handle_response) # (x)
順不同に見えることに注意してください。コードの順序 == 実行順序を維持するために、私は通常、このようなものを分割します。
def sayHello_d(self):
d = self.callRemote(HelloCommand)
d.addCallback(self._sayHello_2)
return d
def _sayHello_2(self, response):
# handle response
pass
これはより良いです。順序付けますが、より冗長になります。ここで、無名関数のトリックを使用します。
d = self.callRemote(HelloCommand)
d.addCallback(define('response', '''
print "callback"
print "got response from", response["name"]
'''))