2015-05-27 7 views
8

Ich habe How to use a context manager inside a decorator and how to pass an object created in decorator to decorated function sowie python decorators with parameters gesehen, und ich versuche, die beiden zu kombinieren ... aber ich kämpfe um meinen Kopf herum.Wie schreibe ich einen Dekorator, um etwas in einen Kontextmanager zu verpacken, der Parameter nimmt?

Ich würde viel lieber die Funktion Werkzeuge @wrap Decorator verwenden, um dies zu tun, wenn möglich, wie ich weiß, ob die Doc-Zeichenfolge beibehalten wird.

Was ich tun möchte, ist dies:

def pyro_opener(func,service,database,port,secret_key): 
    def wrapper(params): 
     with Pyro4.Proxy("PYRO:"+service+"@"+database+":"+port) as obj: 
      obj.set_secret_key(secret_key) 
      return obj.func(params) 
    return wrapper 


@pyro_opener(output_service, employee_db,port=9876,secret_key="h3llow0rld") 
def get_employee_names(salary): 
    return obj.return_employee_names(salary) # obj is clearly not in scope here 
               # but what else can I do? 


get_employee_names(25000) 

>>>> Bob, Jane, Mary 

Ich glaube nicht, dass dies so funktioniert, wobei das Verfahren return_employee_names auf den Dienst am anderen Ende der Verbindung. Soll ich nur den Funktionsaufruf zurückgeben? Wenn ja, wie gebe ich die Params dann ein?

Antwort

6

Sie würden das gebundene Objekt mit an die Wrapped-Funktion übergeben; die Funktion hätte , um ein solches Argument zu akzeptieren.

Dies ist analog wie Methoden funktionieren; sie sind nur Funktionen mit einem zusätzlichen ersten Argumente (self) übergeben:

def pyro_opener(service, database, port, secret_key): 
    def decorator(func): 
     @wraps(func) 
     def wrapper(*args, **kw): 
      with Pyro4.Proxy("PYRO:{}@{}:{}".format(service, database, port)) as obj: 
       obj.set_secret_key(secret_key) 
       return func(obj, *args, **kw) 
     return wrapper 
    retutrn decorator 

@pyro_opener(output_service, employee_db, port=9876, secret_key="h3llow0rld") 
def get_employee_names(obj, salary): 
    return obj.return_employee_names(salary) 

Bitte beachte, dass ich eine andere verschachtelte Funktion im pyro_opener() hinzuzufügen habe es eine richtige Dekorateur Fabrik zu machen.

+0

Also, wenn ich 'get_employee_names' aufrufen, woher bekomme ich den obj param? Außerdem dachte ich, dass die Verwendung von '@ Wraps' bedeutet, dass ich das zusätzliche Niveau der Dekorativität nicht brauchen würde ...? – Pureferret

+0

@Purferret: schau dir genau meine Version von 'get_employee_names()' an; Das Argument 'obj' ist * explizit *. 'functools.wraps()' hat nichts mit Decorator-Factories zu tun, und alles mit dem Kopieren von Metadaten gegenüber der Wrapped-Funktion zum Wrapper, so dass letzteres mehr wie das Original aussieht. –

+0

@martjinpieters was ich meine ist, wenn ich 'get_employee_names' verwenden möchte, muss ich die obj Parameter liefern (gerade Linie, die ich Gehalt liefern muss). Ich kann nicht so die Methode wie 'get_employee_names (???, 300000) nennen', aber was stelle ich für das '???'? – Pureferret