2009-08-18 7 views
0

Je cherche un moyen de décorer une fonction python arbitraire, de sorte qu'une autre fonction soit appelée à la place de l'original, avec tous les paramètres passés en liste ou en dict.Comment remplacer la fonction Python tout en supportant tous les paramètres passés

Plus précisément, quelque chose comme ça (où f est une fonction, et replacement_f prend une liste et un dict):

def replace_func(f, replacement_f): 
    def new_f(*args, **kwargs): 
     replacement_f(args, kwargs) 
    return new_f 

Cependant, je ne peux pas faire référence à l'intérieur replacement_fnew_f. Et je ne peux pas utiliser l'astuce standard de passer replacement_f à new_f comme valeur par défaut pour un paramètre différent, parce que j'utilise les listes d'arguments variables *args et **kwargs.

L'emplacement où la fonction d'origine est appelée ne peut pas changer et accepte les paramètres de position et de nom.

Je crains que ce ne soit pas très clair, mais je suis heureux de clarifier si nécessaire.

Merci

+0

vous avez raison: ce n'est pas clair. Je pense que vous n'avez pas besoin de changer l'appel de la fonction d'origine, mais plutôt sa définition. Si vous ne pouvez pas changer cela, vous ne pouvez probablement pas le décorer non plus. – hop

+0

merci à tous. Je rendais cela beaucoup trop difficile, je peux juste remplacer la fonction sans tous les args, ** kwargs tracas. Aussi, je pense que les règles de portée ont changé depuis Python 1.x, maintenant je peux référencer une variable de la fonction externe dans la définition de la fonction interne. – Mzzzzzz

Répondre

4

pourquoi ne pas essayer tout simplement pas:

f = replacement_f 

exemple:

>>> def rep(*args): 
    print(*args, sep=' -- ') 

>>> def ori(*args): 
    print(args) 

>>> ori('dfef', 32) 
('dfef', 32) 
>>> ori = rep 
>>> ori('dfef', 32) 
dfef -- 32 
0

Si je comprends bien, vous voulez passer tous les arguments d'une fonction à l'autre.

Il suffit de faire:

def replace_func(f, replacement_f): 
    def new_f(*args, **kwargs): 
     replacement_f(*args, **kwargs) # args & kwargs will be expanded 
    return new_f 
0

ce que cela fait ce que vous voulez dire? Non testé

def replace_func(f, replacement_f): 
    nonlocal replacement_f #<<<<<<<<<<<<<<<py3k magic 
    def new_f(*args, **kwargs): 
     replacement_f(*args, **kwargs) # args & kwargs will be expanded 
    replacement_f = new_f 

Python nonlocal statement

modifier: une début, im confus exactement ce que vous voulez, mais je pense que nonlocal aidera

1

Bien que je pense que la réponse de SilentGhost est la meilleure solution si cela fonctionne pour vous Par souci d'exhaustivité, voici la version correcte de ce que vous essayez de faire:

Pour définir un décorateur qui prend un argument, vous devez introduire un niveau supplémentaire:

def replace_function(repl): 
    def deco(f): 
     def inner_f(*args, **kwargs): 
      repl(*args, **kwargs) 

     return inner_f 
    return deco 

Maintenant, vous pouvez utiliser le décorateur avec un argument:

@replace_function(replacement_f) 
def original_function(*args, **kwargs): 
    .... 
+0

quoi fait @ line? –

+0

Voilà comment un décorateur est appliqué à une fonction. – hop

+0

merci, hop. c'est plus proche de ce que je pensais à l'origine – Mzzzzzz

Questions connexes