Python 访问decorator中的可选参数

Python 访问decorator中的可选参数,python,decorator,Python,Decorator,我正在尝试访问传递给decorator中函数的所有参数,包括可选参数。考虑这个例子: def decorator(fn): def wrapper(*args, **kwargs): print 'in wrapper', args, kwargs fn(*args, **kwargs) return wrapper @decorator def myFn(arg1, arg2, arg3=None): print 'in myFn',

我正在尝试访问传递给decorator中函数的所有参数,包括可选参数。考虑这个例子:

def decorator(fn):
    def wrapper(*args, **kwargs):
        print 'in wrapper', args, kwargs
        fn(*args, **kwargs)
    return wrapper

@decorator
def myFn(arg1, arg2, arg3=None):
    print 'in myFn', arg1, arg2, arg3

myFn(1,2)
myFn(1,2,3)
如果我运行这个,我将得到:

in wrapper (1, 2) {}
in myFn 1 2 None
in wrapper (1, 2, 3) {}
in myFn 1 2 3
在第一次运行中,由于我没有指定3个参数,因此出于myFn的目的,arg3被定义为None。但是,
arg3==None
这一事实在decorator内部不可用,无论是在args还是kwargs中。如果我显式地将它传递给myFn,它将显示在装饰器中,但是如果我使用默认值,它将不存在


为什么会这样?这是很正常的,不能“修复”

decorator包装器截取传递给函数的参数和关键字:换句话说,函数调用方传递给函数本身的参数和关键字

arg3=None
是在函数作用域中定义的默认参数。在函数实际被调用(直接调用或通过包装器调用)之前,它不能被拦截,因为此时它不存在

但是,默认值存储在函数对象中:

def fn(arg1,arg2,arg3=None):
    pass

fn.func_defaults
-> (None,)
您可以使用以下命令将默认值映射到参数。。。因此,我认为装饰程序可以尽可能地打印传递的和默认的参数。因此,我假设我的第一条语句不是100%正确:)

您可以使用包来保留函数签名:

from decorator import decorator

def decorate(f):
    def wrapper(f, *args, **kwargs):
        print 'in wrapper', args, kwargs
        return f(*args, **kwargs)
    return decorator(wrapper, f)

@decorate
def myFn(arg1, arg2, arg3=None):
    print 'in myFn', arg1, arg2, arg3

myFn(1, 2)
myFn(1, 2, 3)
myFn(1, 2, arg3=10)
输出:

in wrapper (1, 2, None) {}
in myFn 1 2 None
in wrapper (1, 2, 3) {}
in myFn 1 2 3
in wrapper (1, 2, 10) {}
in myFn 1 2 10

基本上,使用
@decorator
语法就像分配
myFn=decorator(myFn)
。是的,您设置的
arg3=None
在装饰器中并不存在。为什么不使用与
myFn
相同的参数定义包装器呢?其最终目标是让装饰程序查找可选参数(纯文本名称)并返回一个id,以便在myFn中使用。但是我希望能够将它应用到大量函数中,这些函数都有不同的调用签名。所以基本上,直到fn本身在包装器中被实际调用,arg3变量才被定义。很好的解释。我想
decorator.decorator
达到了我在回答中提到的极限?还是有别的把戏?