TL;DR: 関数デコレーターが引数を明確に指定しない場合、装飾された関数には、装飾されていない同じ関数と同じ引数要件 (引数の数と kwarg 名に関して) がありますか?
すべてのショッピング カートの ajax 呼び出しを処理する Web アプリのコントローラーがあります。各呼び出しの開始時に、ショッピング カート機能の実際のロジックを処理するオブジェクトを初期化します。(これは最も効率的な方法ではないかもしれませんが、私の質問は実際のショッピング カートのビットとは何の関係もありません。)
コードは次のようになります。
from webapp import request
from shopping_cart import Cart
from decorators import decorator
@decorator
def init_cart(f, *args, **kwargs):
shopping_cart = Cart()
return f(shopping_cart = cart)
@init_cart
def add_item(shopping_cart = None):
shopping_cart.add(request.params)
@init_cart
def remove_item(shopping_cart = None):
shopping_cart.remove(request.params)
などなど。
そのコードは、複数のアプリによってインポートされて呼び出される集中モジュールに存在します。個々のアプリのコードは次のようになります。
from sharedlib.controllers import cart
from app.base import *
class CartController(BaseController):
def index(self, url = None):
set_content_type('text/javascript')
controller_method = getattr(cart, url)
if controller_method:
return controller_method()
else:
abort(404)
私の質問は次のとおりです。
init_cart デコレーターが受け取った引数を、呼び出されたコントローラー メソッドに渡したい場合は、cart モジュールを渡すだけでなく、次のようにします。
@decorator
def init_cart(f, *args, **kwargs):
shopping_cart = Cart()
kwargs['shopping_cart'] = cart
return f(*args, **kwargs)
@init_cart
def add_item(shopping_cart = None):
shopping_cart.add(request.params)
しかし、例外がスローされ、TypeError: add_item() got multiple values for keyword argument 'shopping_cart'
私はこの振る舞いを完全には理解していません: kwargs は確かに、'shopping_cart' のキーと値のペアを 1 つしか持っていません。
さらに、これを試してみると:
@decorator
def init_cart(f, *args, **kwargs):
shopping_cart = Cart()
return f(cart)
@init_cart
def add_item(shopping_cart = None):
shopping_cart.add(request.params)
エラーが発生しますTypeError: add_item() takes exactly 1 argument (0 given)
私は、引数の受け取りと受け渡しに関して、デコレーターがどのように振る舞うかをどうにか理解していないと仮定していinit_cart
ます(*args, **kwargs)
. そうではないようです。
さらに、前の例では、どのようにしてメソッドがshopping_cart
引数に対して複数の値を受け取ることができるのでしょうか?