装饰函数以向函数添加自定义参数

时间:2013-09-11 02:12:31

标签: python arguments decorator

我有兴趣创建一个泛型函数并用它来装饰所有其他函数。新函数将包含来自两个函数的参数。实施例

def decorator(func):
    Some chunk of code

@decorator
def func(a,b):
    print a**2,b**2
    return a**2,b**2

#Equivalent func of what I want out of the decorator
def equiv_func(a,b,var):
    print var # I want to modify all decorated functions to accept a new
              # argument and print it using "print var"
    print a**2, b**2
    return a**2, b**2

这就是我想出来的......但

def decor(func):
    def modify(var,**kwargs):
       print var
       x,y=func(**kwargs)
       return x,y
    return modify

@decor
def func(a,b):
    print a**2,b**2
    return a**2,b**2

>>> func(var="hi",a=4,b=5)
hi
16 25

我使用** kwargs作为计算func参数的方法,但这迫使我使用func(var =“hi”,a = 4,b = 5)而不是func(a = 4,b = 5,var =“hi”)由于** kwargs的定位。

此外,当我需要它时,这个解决方法阻止我在定义我的装饰器时使用** kwargs,因为它已经被用于将参数输入到func中。实施例

def test(**kwargs):
    if 'test_ans' in kwargs:
        if kwargs['test_ans']=='y':
            return True
    else:
        return False

def decor(func):
    def modify(var,**kwargs):
       if test(**kwargs): # I need to use **kwargs here, but I also need it to define my  
                          # arguments in func.
           print var
       x,y=func(**kwargs)
       return x,y
    return modify

...
# The following is what I expect but due to **kwargs being used for two purposes, 
# it doesn't work
>>>func(var='hi',a=4,b=5,test_ans='y')
'hi'
16 25
>>>func(var='hi',a=4,b=5,test_ans='n')
16 25

我希望我的问题很明确。这些例子只是为了说明我面临的限制。它们不是实际代码(我不会编写一个使用** kwargs的测试函数) 感谢任何提前帮助,编码专家!

编辑: 或简单地说,有没有其他方法可以修改func(a,b)到func(a,b,c,d,e,...,** kwargs)而不在装饰器中使用kwargs?

2 个答案:

答案 0 :(得分:1)

您可以通过

调用func
func(a=4, b=5, var="hi") 

使var成为关键字参数。

def decor(func):
    def modify(*args, **kwargs):
        var = kwargs.pop('var', None)
        print var
        x,y=func(*args, **kwargs)
        return x,y
    return modify

@decor
def func(a,b):
    print a**2,b**2
    return a**2,b**2

func(a=4, b=5, var="hi")
func(a=4, b=5)

答案 1 :(得分:1)

试试这个。您可以使用func.func_code.co_varnames访问函数接受的参数。一旦你知道了,你可以过滤掉其他所有内容。

编辑:这是有限的,因为如果myfunc接受**kwargs作为参数,您将无法有效使用此功能。

def print_decorator(func):
    def wrapped(*args, **kwargs):
        # a tuple of the names of the parameters that func accepts
        func_params = func.func_code.co_varnames
        # grab all of the kwargs that are not accepted by func
        extra = set(kwargs.keys()) - set(func_params)

        for kw in extra:
            print kwargs.pop(kw)

        return func(*args, **kwargs)

    return wrapped

@print_decorator
def myfunc(a, b, c=None):
    print 'myfunc was passed: a={}, b={}, c={}'.format(a, b, c)
    return a, b, c

>>> myfunc(1, b=2, c=3, d=4, e=5)
4
5
myfunc was passed: a=1, b=2, c=3