2015-05-27 18 views
8

Ho visto How to use a context manager inside a decorator and how to pass an object created in decorator to decorated function e python decorators with parameters, e sto provando a combinare i due ... ma sto lottando per capirlo.Come si scrive un decoratore per racchiudere qualcosa in un gestore di contesto, che richiede parametri?

Preferirei usare gli strumenti di funzione @wrap decoratore per eseguire questa operazione se possibile, poiché so che manterrà la stringa doc.

Quello che voglio fare è questo:

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 

Non credo che questo funziona in questo modo, il metodo return_employee_names è in servizio presso l'altra estremità della connessione. Dovrei semplicemente restituire la chiamata di funzione? Se sì, come faccio a passare i parametri in poi?

risposta

6

Si passerà l'oggetto associato a with ... as alla funzione di avvolgimento; la funzione sarebbe avere per accettare tale argomento.

Questo è analogo a come funzionano i metodi; sono solo funzioni con un primo argomento extra (self) superato in:

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) 

Nota che ho dovuto aggiungere un'altra funzione annidata nel pyro_opener() per renderlo una vera e propria fabbrica di decoratore.

+0

Quindi quando chiamo 'get_employee_names' da dove ottengo il parametro obj? Inoltre, pensavo che l'uso di '@ wraps 'significherebbe che non avrei bisogno del livello extra di decorazione ...? – Pureferret

+0

@Pureferret: guarda da vicino la mia versione di 'get_employee_names()'; l'argomento 'obj' è * esplicito *. 'functools.wraps()' non ha nulla a che fare con le fabbriche di decoratori, e tutto con la copia dei metadati dalla funzione wrapper al wrapper, in modo che quest'ultimo appaia più simile all'originale. –

+0

@martjinpieters cosa intendo dire, quando voglio usare 'get_employee_names' ho bisogno di fornire i parametri obj (solo la riga che ho bisogno di fornire stipendio). Non posso chiamare il metodo come "get_employee_names (???, 300000)' ma cosa devo inserire per '???'? – Pureferret

Problemi correlati