关于python:在装饰器的包装器上访问kwargs和args

Get access to kwargs and args at the wrapper of decorator

我有一个基于类的装饰师。问题是我需要能够访问wraped函数args和kwargs,但现在我不能,也不明白为什么。这应该很容易,但对我来说不是。

1
2
3
4
5
6
7
8
9
10
11
class limit:
    def __call__(self, fn):
        @wraps(fn)
        # the idea to use signature like (request, *args, **kwargs) is bad. I must accept *args and **kwargs only
        def wrapper(*args, **kwargs):
             # pdb breakpoint is here
             user = kwargs.get('user') or kwargs.get('request').user // ERROR

             return fn(*args, **kwargs)

        return wrapper

让我们来看看PDB。那太疯狂了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(Pdb) args
args = (<User: dua>,)
kwargs = {}
(Pdb) kwargs
{}
(Pdb) args.args
args = (<User: dua>,)
kwargs = {}
(Pdb) args.args.args.args
args = (<User: dua>,)
kwargs = {}
(Pdb) args.get('user')
args = (<User: dua>,)
kwargs = {}
(Pdb) type(args)
<class 'tuple'>
(Pdb)

问题是,我如何才能访问args、kwargs并将args视为列表,将kwargs视为dict。

另外,我不知道为什么args和kwargs看起来像那样。为什么他们看起来像那样?

如答案所述,args是PDB的命令。用户repr(args)查看args。

下一个问题是函数的可能签名:1)def fn(请求,…)2)def fn(self、a、b、c等,用户)3)DEF FN(用户)

有没有办法用一个装饰师来处理所有的问题?


您的pdb输出并不真正相关,args在这里的作用类似于交互式PDB命令。

为了简单起见,可以使用repr(args)或临时重命名*args参数。


我最终得到了这个解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
def wrapper(*args, **kwargs):
    user = None
    fn_signature_args = inspect.getfullargspec(fn).args
    # looking for a user in kwargs
    if 'user' in kwargs:
    user = kwargs['user']
    # looking for a user as positional argument
    elif 'user' in fn_signature_args:
    index = fn_signature_args.index('user')
    user = args[index]
    # looking for a user as self or request attribute
    elif fn_signature_args[0] in ('request', 'self'):
    user = args[0].user