TL;DR:如果函数装饰器没有具体指定参数,那么装饰函数是否具有与未装饰函数相同的参数要求(在参数计数和参数名称方面)?
我有一个 web 应用程序的 Controller ,它处理所有购物车 ajax 调用。在每次调用开始时,它都会初始化一个对象,该对象处理购物车功能的实际逻辑。 (这可能不是最有效的方法,但我的问题与实际的购物车位没有任何关系。)
代码如下所示:
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 装饰器将它接收到的参数传递给被调用的 Controller 方法,除了传递 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”。
此外,如果我尝试这样做:
@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 参数接收多个值?
请您参考如下方法:
def this_is_a_decorator(fn):
def decorated_fn(*args,**kwargs):
result = fn(*args,**kwargs) #notice we are calling the original function
return "%s decorated"%result
return decorated_fn
@this_is_a_decorator
def reverse_string(msg=""):
return msg[::-1]
print reverse_string("Hello!")
为你的装饰器
def init_cart(fn):
def decorated_fn(*args,**kwargs):
cart = Cart()
fn(cart)
return cart
return decorated_fn
@init_cart
def add_item(shopping_cart=None):
shopping_cart.add(request.params)
