Python Decorator覆盖函数参数

时间:2017-02-22 05:24:23

标签: python decorator python-decorators

我正在尝试编写一个python装饰器来覆盖一个函数参数,但我真的不知道要放在inner()函数中。在这里修改args的正确方法是什么?

In [9]: print articles['status']
Out[9]: u'OK'

3 个答案:

答案 0 :(得分:3)

def override(*override_args, **override_kwargs):
    def outer(f):
        def inner(*args, **kwargs):
            min_args_length = min(len(args), len(override_args))
            args = list(args)
            for i in xrange(min_args_length):
                args[i] = override_args[i]
            kwargs.update(override_kwargs)
            return f(*args, **kwargs)
        return inner
    return outer

@override('Cat', 'male', k1='0')
def my_function(animal, **kwargs):
    print animal
    print kwargs

my_function('Mouse', k1='1', k2='10')

输出:

Cat
{'k2': '10', 'k1': '0'}

解释

args是一个包含没有名字的args的元组,我们可以覆盖它们的最多min(len(args),len(override_args))。

kwargs是一个包含命名args作为键:值对的dict。只需将override_kwargs更新为kwargs

即可

我强烈建议您只覆盖命名args“kwargs”以防止不匹配args的顺序。

答案 1 :(得分:0)

我已经简化了你的例子。只是想知道装饰器中哪个位置的参数。

def override(dec_animal):
    def outer(func):
        def inner(animal_to_be_ignored, **kwargs):
            # print animal_to_be_ignored ==> This is mouse
            return func(dec_animal, **kwargs)
        return inner
     return outer


@override('Cat')
def my_function(animal, **kwargs):
    print animal
    print kwargs


my_function('Mouse', k1='1', k2='10')

输出:

Cat {'k2': '10', 'k1': '1'}

答案 2 :(得分:0)

class override_func_params(object):
    def __init__(self, *args, **kwargs):
        self.override_args = args
        self.override_kwargs = kwargs

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            if kwargs:
                kwargs.update(self.override_kwargs)
            if args:
                args = list(args)
                for index, value in enumerate(self.override_args):
                    try:
                        args[index] = value
                    except IndexError:
                        break
                args = tuple(args)
            return func(*args, **kwargs)
        return wrapper


@override_func_params('a', k=1)
def foo(*args, **kwargs):
    print args, kwargs

不带参数调用。

>>> foo()
>>> (), {}

使用参数调用,参数被覆盖。

>>> foo('b', k=2)
>>> ('a',), {'k': 1}