2017-12-04 122 views
6

kullanarak değiştiriyorum. Python dekoratörünü kullanmayı öğreniyorum.Python: Bir işlevin iç davranışını dekoratör

def my_dcrtr(fun): 
    def new_fun(): 
     return fun() 
    return new_fun 

Dekoratörün içinde bir siyah kutu gibi işlev gören "eğlenceli" işlevinin gerçekleştirildiğini anlıyorum. New_fun içinde eğlenmeyi() kullanmayı veya hiç kullanmamayı seçebilirim. Bununla birlikte, eğlenceye girip giremeyeceğimi ve new_fun içinde eğlencenin yerel kapsamıyla etkileşime girip giremeyeceğimi bilmiyorum.

örn. Python ile bir oyuncak Uzaktan Yordam Çağrısı (RPC) yapmaya çalışıyorum. Bu örnekte

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)) 

, ben 'halk()' komutuyla zamanında rpc_fun argümanı listesini elde etmeye çalışmak. Sonra yürütmek için sunucuya gönderin. Rpc_fun yerlilerini() döndürmesine izin vermek yerine, dekore edilmiş fonksiyonun argüman alanını almak için dekoratör kullanmak mümkün mü?

cevap

3

Sen Python3 için işlev ek açıklamaları kullanabilirsiniz:

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)) 

Çıktı: Bu şekilde

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

, buradan dekore işlevin parametrelerini ve belirlediği ileri bilgilere erişmek için sarıcı işlevi decorated_fun kullanıyor ek açıklama. Ek açıklamalardaki parametre açıklamalarını değiştirdim, böylece her dize değeri args'u dizinlemek için kullanılabilecek bir basamakta bitecek. Bununla birlikte, ek açıklamalarda parametre açıklamalarını değiştirmek istemiyorsanız, bitiş karakteri ile sıralayabilirsiniz.

Düzenleme: sarma fonksiyonu (decorated_fun) olarak adlandırılan zaman my_funct gövdesinde kod geçirilir decorated_fun kapsamında ilan local_args çözdükten, args beri yürütülür.

+0

Bunun nasıl çalıştığını anlamıyorum. İhtiyacım olan şey, 'decorated_fun' içinde 'fun_parameters' değerini çalışma zamanında {'a': 10, 'b': 20, 'c': 30} 'e eşit olacak şekilde yapmak, böylece sunucuya gönderebileceğim. Mümkün mü? –

+0

@ShichuZhu lütfen son düzenlemeye bakın. – Ajax1234

+0

Harika! Bu benim problemimi mükemmel bir şekilde çözer! Eğer sakıncası yoksa kalan iki soru: 1. İşlev bedenindeki her şey (yani a + b + c) hiçbir zaman idam edilmeyecek, değil mi? 2. (nvm ... Bir hata yaptım ...) –