2016-06-09 43 views
2

我想做一个Python装饰器,它可以接受一个参数(它正在装饰的函数中的参数的名称)并使用该参数来查找函数中参数的值。我知道这听起来超级混乱,哈!但我想做的事情是这样的(它是一个烧瓶Web应用程序):Python装饰器访问参数的名字

这就是我现在所拥有的:

@app.route('/admin/courses/<int:course_id>') 
def view_course(course_id): 
    ... view code here 

我想要做这样的事情:

@app.route('/admin/courses/<int:course_id>') 
@access_course_permission(course_id) 
def view_course(course_id): 
    ... view code here 

现在我知道我可以这样做:

def access_course_permission(f): 
    @wraps(f) 
    def decorated_function(*args, **kwargs): 
     # check args[0] right here to find the course ID 
     return f(*args, **kwargs) 
    return decorated_function 

其巨大只要COURSE_ID总是工作第一个参数。但事实并非如此。这就是为什么我想能够指定名称。

如果这是不可能的,我想我可以传递参数给装饰的指标,但不是很漂亮...

回答

2

可以使用inspect.getargspec() function访问中使用的名称一个函数:

def access_course_permission(argument_name): 
    def decorator(f): 
     argspec = inspect.getargspec(f) 
     argument_index = argspec.args.index(argument_name) 
     def wrapper(*args, *kwargs): 
      try: 
       value = args[argument_index] 
      except IndexError: 
       value = kwargs[argument_name] 
      # do something with value 
      return f(*args, **kwargs) 
     return wrapper 
    return decorator 

上面找出你的具体参数在哪个索引位置;这涵盖了位置和关键字参数(因为在Python中,您也可以通过位置传递关键字参数的值)。

不过请注意,对于您的具体的例子,瓶将调用view_coursecourse_id作为关键字参数,所以使用kwargs[argument_name]就足够了。

你必须在传递来命名这样的说法:

@app.route('/admin/courses/<int:course_id>') 
@access_course_permission('course_id') 
def view_course(course_id): 
    # ... view code here 
+0

这工作!非常感谢。 – ian93