从装饰器传递位置参数时如何支持静态和类方法?

Posted

技术标签:

【中文标题】从装饰器传递位置参数时如何支持静态和类方法?【英文标题】:How to support static and class methods when passing positional arguments from a decorator? 【发布时间】:2016-07-03 16:46:55 【问题描述】:

我想编写一个装饰器,它在第一个位置(但在selfcls 之后)将附加位置参数传递给包装函数。

def handle_route(self, url, headers):
    pass

@require_login
def handle_route(self, user, url, headers):
    pass

既然有静态方法、类方法和普通方法,我怎么知道在什么位置传递附加参数?

import functools

def require_login(function):
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        user = obtain_user(kwargs.get('headers', ))
        return function(user, *args, **kwargs)
    return wrapper

此示例仅用于静态方法。在其他情况下,用户作为 selfcls 参数传递,从而导致错误。

【问题讨论】:

【参考方案1】:

最好使用装饰器class,而不是装饰器函数。然后,您可以实现完整的descriptor protocol,否则它会从函数继承。

具体来说,您需要为您的对象创建一个__get__ 方法。然后,您可以将 class-/static-/regular-method 的解析推迟到包装的方法。

class RequireLogin(object):
  def __init__(self, wrapee):
    self.wrapee = wrapee
    self.user = 'foo' # changeme

  def __get__(self, instance, owner):
    def wrapped(*args, **kwargs):
      return self.wrapee.__get__(instance, owner)(self.user, *args, **kwargs)
      #                  ^ use class/static/regular method's __get__
    return wrapped

【讨论】:

以上是关于从装饰器传递位置参数时如何支持静态和类方法?的主要内容,如果未能解决你的问题,请参考以下文章

使用Typescript和类组件装饰器时如何将数组传递给Vue中的props

Python的静态方法和类方法

函数小结

函数 阶段总结

Python-4 函数和装饰器

函数嵌套与装饰器