2017-12-04 8 views
6

Ich lerne, Python Decorator zu verwenden.Python: Ändern Sie das interne Verhalten einer Funktion mit Dekorator

Ich erkenne die verzierte Funktion "Spaß" wirkt wie eine Blackbox im Dekorateur. Ich kann wählen, Spaß() oder überhaupt nicht innerhalb new_fun zu verwenden. Ich weiß jedoch nicht, ob ich in "Spaß" einsteigen und mit der lokalen Reichweite von Fun innerhalb der new_fun interagieren kann.

z.B. Ich versuche, mit Python einen Remote Procedural Call (RPC) zu machen.

def return_locals_rpc_decorator(fun): 
    def decorated_fun(*args, **kw): 
     local_args = fun(*args, **kw) 
     # pickle the local_args and send it to server 
     # server unpickle and doing the RPC 
     # fetch back server results and unpickle to results 
     return rpc_results 

    return decorated_fun 


@return_locals_rpc_decorator 
def rpc_fun(a, b, c=3): 
    return locals() # This looks weird. how can I make this part of the decorator? 


print(rpc_fun(2, 1, 6)) 

In diesem Beispiel versuche ich rpc_fun Argument Liste zur Laufzeit mit den ‚Einheimischen()‘ Befehl zu erhalten. Dann senden Sie es zur Ausführung an den Server. Anstatt zuzulassen, dass rpc_fun seine Locals() zurückgibt, ist es möglich, den Decorator zu verwenden, um den Argumentraum der verzierten Funktion abzurufen?

Antwort

3

Sie können Funktion Anmerkungen für Python3 verwenden:

def return_locals_rpc_decorator(fun): 
    def decorated_fun(*args, **kw): 
     local_args = fun(*args, **kw) 
     print(local_args) 
     fun_parameters = fun.__annotations__ 
     final_parameters = {a:list(args)[int(b[-1])-1] for a, b in fun_parameters.items() if a != 'return'} 
     return final_parameters 
    return decorated_fun 

@return_locals_rpc_decorator 
def my_funct(a:"val1", b:"val2", c:"val3") -> int: 
    return a + b + c 

print(my_funct(10, 20, 30)) 

Ausgang:

60 
{'a': 10, 'b': 20, 'c': 30} 

Auf diese Weise Sie werden mit der Wrapper-Funktion decorated_fun durch die dekorierten Funktion der Parameter und weitere Informationen angegeben zuzugreifen die Anmerkung. Ich habe die Parameterbeschreibungen in den Annotationen so geändert, dass jeder String-Wert in einer Ziffer endet, die zum Indizieren von args verwendet werden kann. Wenn Sie die Parameterbeschreibungen in den Anmerkungen jedoch nicht ändern möchten, können Sie nach Endzeichen sortieren.

Edit: der Code in dem Körper my_funct wird, wenn in der Wrapper-Funktion (decorated_fun), da die args, erklärte im Rahmen der decorated_fun wird weitergegeben und ausgepackt in local_args genannt ausgeführt.

+0

Ich verstehe nicht, wie das funktioniert. Was ich brauche, ist, 'fun_parameters' innerhalb der 'distributed_fun' gleich {'a': 10, 'b': 20, 'c': 30} zur Laufzeit zu machen, damit ich es an den Server senden kann. Ist das möglich? –

+0

@ShichuZhu siehe meine letzte Änderung. – Ajax1234

+0

Super! Das löst mein Problem perfekt! Zwei verbleibende Fragen, wenn es Ihnen nichts ausmacht: 1. Alles im Körper der Funktion (d. H. A + b + c) wird niemals ausgeführt, oder? 2. (nvm ... Ich habe einen Fehler gemacht ...) –

Verwandte Themen