2017-02-22 8 views
2

私は関数の引数をオーバーライドするためのpythonデコレータを作成しようとしていますが、実際にはinner()関数の中に何を入れるべきか分かりません。ここでargを変更する適切な方法は何ですか?Python Decoratorは関数の引数をオーバーライドします

def override(*override_args, **override_kwargs): 
     def outer(f): 
      def inner(*args, **kwargs): 
       ... 
       ... 
      return inner 
     return outer 

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

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

答えて

2
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'} 

説明:

引数をタプルには名前なし引数が含まれている、我々は(override_args)lenは、ほとんど分(LEN(引数)で上書きすることができます) そのうちの。

kwargsには、名前付き引数がkey:valueのペアとして含まれています。 override_kwargsをkwargsに更新するだけです。

そして、不一致argsの順序を防ぐために、名前付きargs "kwargs"をオーバーライドすることを強くお勧めします。

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'}

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} 
関連する問題