2017-02-22 1 views
2

Je suis en train d'essayer d'écrire un décorateur python pour remplacer un argument de fonction, mais je suis vraiment perdu à ce qu'il faut mettre dans la fonction inner(). Quelle est la bonne façon de modifier les arguments ici?Argument de remplacement de la fonction 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') 

Répondre

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

sortie:

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

expliquer:

args est un tuple contient args sans nom, nous pouvons remplaçons au plus min (LEN (args), len (override_args)) d'eux. Kwargs est un dict contient des arguments nommés en tant que clés: paires de valeurs. Il suffit de mettre à jour override_kwargs pour kwargs

Et je vous suggère fortement de ne remplacer que les arguments nommés "kwargs" pour empêcher l'ordre des arguments de non-concordance.

0

J'ai simplifié votre exemple. Essayez juste de vous faire une idée de ce que les paramètres viennent à quel endroit dans le décorateur.

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

Sortie:

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 

Appel sans arguments.

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

Appel avec arguments, les arguments sont remplacés.

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