0

私はPythonを初めて使用し、デコレータについて学んでいます。Flask をいじった後、デコレータ (引数付き) がどのように機能するかを理解するために、ルート ハンドラ/デコレータをシミュレートするコードを記述しようとしています。

以下のコードでは、スクリプトが実行されると、ルート デコレーターが自分自身を呼び出しているように見えます。私の質問は、app.route()このスクリプトを実行したときに が呼び出される可能性はありますか?ここで実際に何が起こっているのでしょうか? index()関数をどこでも直接呼び出していないことに注意してください。

# test.py

class Flask(object):

    def __init__(self, name):
        self.scriptname = name

    def route(self, *rargs, **kargs):
        args = list(rargs)
        if kargs:
            print(kargs['methods'])
        def decorator(f):
            f(args[0])
        return decorator

app = Flask(__name__)

@app.route("/", methods = ["GET","PUT"])
def index(rt):
    print('route: ' + rt)

上記は私の端末にこれを出力します:

$ python test.py
['GET', 'PUT']
route: /

任意の洞察をいただければ幸いです。

4

2 に答える 2

2

@app.route("/", methods = ["GET","PUT"])実行ステートメントroute()です。アプリ オブジェクトのメソッドを呼び出します。モジュールレベルなので、スクリプトのインポート時に実行されます。

これで、呼び出しの結果app.route(...)は関数になり、 を使用し@てデコレーターとしてマークしたため、その関数は をラップしindexます。構文はこれの単なるショートカットであることに注意してください。

index = app.route(...)(index)

つまり、Python はapp.route()withによって返された関数をパラメーターとして呼び出し、結果を新しい関数indexとして格納します。index

ただし、ここではレベルがありません。パラメータのない通常のデコレータは、次のように記述します。

@foo
def bar()
   pass

モジュールがインポートされると、foo()が実行され、ラップする関数が返されますbar。しかし、デコレータ呼び出し内でroute()関数を呼び出しています! したがって、実際には、関数自体が元の関数をラップする関数を返すデコレータ関数を返す必要があります...ヘッドスクラッチ、確かに。

メソッドrouteは次のようになります。

def route(self, *rargs, **kargs):
    args = list(rargs)
    if kargs:
        print(kargs['methods'])
    def decorator(f):
        def wrapped(index_args):
            f(args[0])
        return wrapped
    return decorator
于 2013-09-30T20:30:25.073 に答える
-1

基本的に...app.route(index, "/", ["GET", "PUT"])関数です。そして、これは index の代わりに呼び出される関数です。

コードでは、 を呼び出すとindex()、 が呼び出されますapp.route(index, "/", ["GET", "PUT"])。これは print から始まりkargs['methods']、次にデコレータ関数を作成します:

def decorator(f):
    f(args[0])

このデコレーターは、装飾された関数 ( f) を 1 つの引数(args[0]ここでは "/") で呼び出します。これは印刷されroute: /ます。

私が見つけたデコレータの最良の説明はここにあります:関数デコレータのチェーンを作るには?

自己発火が必要ない場合は、次の方法でデコレータを定義できます。

def route(*rargs, **kargs):
    args = list(rargs)
    if kargs:
        print(kargs['methods'])
    def decorator(f):
        f(args[0])
    return decorator

@app.route("/", methods = ["GET","PUT"])
def index(rt):
    print('route: ' + rt)

ただし、常にwhich が常に...で呼び出さrtれるため、 index の引数は使用されません。routeindexargs[0]\

于 2013-09-30T20:18:58.237 に答える