4

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"]
'''))
4

1 に答える 1

1

JavaScript または Ruby のバックグラウンドを持っている場合、無名関数を処理する Python の機能は確かに制限されているように見えるかもしれませんが、これには理由があります。Python の設計者は、簡潔さよりもコードの明快さの方が重要であると判断しました。それが気に入らないのなら、おそらく python がまったく好きではないでしょう。それは何も悪いことではありません。他にもたくさんの選択肢があります。自分にとってよりおいしい言語を試してみませんか?

コードのチャンクを文字列に入れてその場で解釈することは、言語を「拡張」するための間違いなく間違った方法です。なぜなら、構文ハイライターからPythonインタープリター自体まで、使用しているツールがどれも処理できないからです。賢明な方法で「文字列化」されたコード。

尋ねられた質問に答えるには:あなたがしていることは、本質的に、Pythonよりも優れたプログラミング言語を構築し、その場でPythonにコンパイルしようとすることです。このアイデアはスクリプト言語の世界では新しいものではなく、生産的である場合もそうでない場合もあります (CoffeeScript は実装の成功例です) が、あなたのアプローチそのものが間違っています。format()コードを操作するときに探しているツールではありません。コンパイラを作成している場合は、適切に実行してください。パーサー (pyparsing など) を使用して AST 内のコードを読み取り、AST をウォークスルーして Python コード (またはバイトコード) を生成し、構文エラーをキャッチして対策を講じます。より良いランタイム フィードバック (エラー コンテキスト、行番号など) を提供します。最後に、コンパイラがさまざまな Python バージョンと実装で動作することを確認してください。

または単にルビーを使用してください。

于 2013-03-27T11:57:11.267 に答える