2009-08-18 9 views
0

Ich suche nach einer Möglichkeit, eine beliebige Python-Funktion zu dekorieren, so dass eine alternative Funktion anstelle des Originals mit allen Parametern als Liste oder Diktat übergeben wird.Wie Python-Funktion zu ersetzen, während alle übergebenen Parameter unterstützt

Genauer gesagt, so etwas wie dieses (wobei f eine beliebige Funktion ist, und replacement_f nimmt eine Liste und eine dict):

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

Allerdings kann ich nicht replacement_f innerhalb new_f verweisen. Und ich kann nicht den Standardtrick verwenden, replacement_f zu new_f als Standard für einen anderen Parameter zu übergeben, weil ich die variablen Argumentlisten *args und **kwargs verwende.

Die Position, an der die ursprüngliche Funktion aufgerufen wird, kann sich nicht ändern und akzeptiert sowohl positionale als auch benannte Parameter.

Ich fürchte, das ist nicht sehr klar, aber ich bin froh, wenn nötig zu klären.

Dank

+0

Sie haben recht: dies ist nicht klar. Ich denke, Sie müssen den Aufruf der ursprünglichen Funktion nicht ändern, sondern ihre Definition. Wenn Sie das nicht ändern können, können Sie es wahrscheinlich auch nicht dekorieren. – hop

+0

danke allen. Ich habe das alles viel zu schwierig gemacht, ich kann einfach die Funktion ohne all die * args, * kwargs stress ersetzen. Ich glaube auch, dass sich die Bereichsregeln seit Python 1.x geändert haben, jetzt kann ich eine Variable von der äußeren Funktion innerhalb der inneren Funktionsdefinition referenzieren. – Mzzzzzz

Antwort

4

, warum Sie nicht nur versuchen:

f = replacement_f 

Beispiel:

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

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

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

Wenn ich das richtig verstehe, wollen Sie alle Argumente von einer Funktion zur anderen zu übergeben.

einfach tun:

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

das, was Sie tut das? Ungeprüfte

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

edit: es ist ein Anfang, ich bin genau verwirrt, was Sie wollen, aber ich denke, nonlocal

1

helfen Obwohl ich SilentGhost Antwort denken, ist die beste Lösung, wenn es für Sie arbeitet , der Vollständigkeit halber, hier ist die korrekte Version von dem, was Sie versucht haben zu tun:

Um einen Dekorator zu definieren, der ein Argument nimmt, müssen Sie eine zusätzliche Ebene einführen:

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

     return inner_f 
    return deco 

Jetzt können Sie den Dekorateur mit einem Argument verwenden:

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

was macht @ line? –

+0

So wird ein Decorator auf eine Funktion angewendet. – hop

+0

danke, hop. Das ist näher an dem, was ich ursprünglich dachte – Mzzzzzz