1

我有兴趣创建一个通用函数并用它装饰所有其他函数。新函数将包含两个函数的参数。例子

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 的测试函数)提前感谢您的任何帮助,编码大师!

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

4

2 回答 2

2

你可以允许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)
于 2013-09-11T02:20:34.770 回答
2

尝试这个。您可以使用 访问函数接受的参数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
于 2013-09-11T03:11:59.250 回答