2011-08-18 12 views
9

Örnek argümanı kullanarak kendini örnek olarak bir dekoratör olarak bir decorator kullanarak örnek kodları süslemek için aşağıdaki kodu kullanarak geldim:Python: Örnek özniteliklerini örnek yöntemlerle dinamik olarak atama ile ilgili bir sorun var mı?

from functools import wraps 

def logging_decorator(tricky_instance): 
    def wrapper(fn): 
     @wraps(fn) 
     def wrapped(*a, **kw): 
      if tricky_instance.log: 
       print("Calling %s.." % fn.__name__) 
      return fn(*a, **kw) 
     return wrapped 
    return wrapper  

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 
     self.say_hi = logging_decorator(self)(self.say_hi) 

    def say_hi(self): 
     print("Hello, world!") 


i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 

Bu harika çalışıyor, ama korkarım ki yanıltıcı bazı yan etkileri gözden kaçmış olabilirim Bu hile. Kendimi yürüyerek vurmak mıyım yoksa bu güvenli mi?

Bunu aslında kayıt için kullanmak istemediğimi unutmayın, bu benim gelebileceğim en kısa anlamlı örnek.

+0

Yasal olarak görünüyor. Benim nacizane fikrime göre. – Evpok

cevap

2

Sanırım gereksiz akıllı olmaya çalışıyordum. Utanç verici bir çözüm var gibi görünüyor:

from functools import wraps 

def logging_decorator(fn): 
    @wraps(fn) 
    def wrapped(self, *a, **kw): 
     if self.log: 
      print("Calling %s.." % fn.__name__) 
     return fn(self, *a, **kw) 
    return wrapped 

class Tricky(object): 
    def __init__(self, log): 
     self.log = log 

    @logging_decorator 
    def say_hi(self): 
     print("Hello, world!") 

i1 = Tricky(log=True) 
i2 = Tricky(log=False) 

i1.say_hi() 
i2.say_hi() 
4

Bunu neden yapmak isteyeceğiniz bana açık değil. Eğer örneğin bir şey yapmak istiyorsanız,

import types 

class Tricky(object): 
    def __init__(self): 
     def method(self): 
      print('Hello') 
     self.method = types.MethodType(method, self) 

o __init__ yönteminde yapın: Yeni bir yöntem türü atamak isterseniz dinamik types kullanın.

def decorator(tricky_instance): 
    def wrapper(meth): 
     print(meth.im_self == tricky_instance) 
     return meth 
    return wrapper 

Şahsen ben bu Belki-I-Shouldn't-Kullanımı-Dekoratörler arazi içine veering olduğunu düşünüyorum: Sadece dekoratör iç yöntemin örneğine erişim istiyorsanız, im_self özelliğini kullanabilirsiniz.

+0

Özel durumlarla belirtilen örnek (geçici) ağ sorunlarındaki örnek yöntemlerini otomatik olarak çağırmak istiyorum. Hangi istisnalar geçicidir ve kalıcı olanlar asıl örneğe bağlıdır (örnekler, tutarlılığı depo yerine bağlı olan Amazon S3 nesnelerini temsil eder). – Nikratio

+0

Kodunuzun ne için iyi olduğunu anlamıyorum. Detaylandırır mısınız? – Nikratio

+1

Kodum, __init__' içinde yeni bir örnek yöntemi oluşturur. Sanırım bir dekoratör yazmaya çalışıyorsunuz ve dekoratörün dekoratörün genelleştirilmesi için dekore edilen yöntemin örneğine erişmesini mi istiyorsunuz? – zeekay

İlgili konular