2009-11-05 31 views
7

sınıfında kullanıldığında başarısız olur Sınıf yöntemlerinde kullanmak üzere dekoratörler oluştururken, dekoratör mekanizması bir işlev/kapatma yerine bir sınıf olduğunda sorun yaşıyorum. Sınıf formu kullanıldığında, dekolayıcım bağlı bir yöntem olarak ele alınmaz.Sınıf üyelerindeki Python dekoratörleri, dekoratör mekanizması sınıf

Genellikle dekoratörler için işlev formunu kullanmayı tercih ediyorum ancak bu durumda ihtiyacım olanı uygulamak için mevcut bir sınıfı kullanmam gerekiyor.

Bu, python-decorator-makes-function-forget-that-it-belongs-to-a-class ile ilişkili gibi görünüyor ama neden işlev formu için sorun çözebilir?

Tüm ziyaretleri göstermek için yapabileceğim en basit örnek aşağıdadır.

def decorator1(dec_param): 
    def decorator(function): 
     print 'decorator1 decoratoring:', function 
     def wrapper(*args): 
      print 'wrapper(%s) dec_param=%s' % (args, dec_param) 
      function(*args) 
     return wrapper 
    return decorator 

class WrapperClass(object): 
    def __init__(self, function, dec_param): 
     print 'WrapperClass.__init__ function=%s dec_param=%s' % (function, dec_param) 
     self.function = function 
     self.dec_param = dec_param 

    def __call__(self, *args): 
     print 'WrapperClass.__call__(%s, %s) dec_param=%s' % (self, args, self.dec_param) 
     self.function(*args) 

def decorator2(dec_param): 
    def decorator(function): 
     print 'decorator2 decoratoring:', function 
     return WrapperClass(function, dec_param) 
    return decorator 

class Test(object): 
    @decorator1(dec_param=123) 
    def member1(self, value=1): 
     print 'Test.member1(%s, %s)' % (self, value) 

    @decorator2(dec_param=456) 
    def member2(self, value=2): 
     print 'Test.member2(%s, %s)' % (self, value) 

@decorator1(dec_param=123) 
def free1(value=1): 
    print 'free1(%s)' % (value) 

@decorator2(dec_param=456) 
def free2(value=2): 
    print 'free2(%s)' % (value) 

test = Test() 
print '\n====member1====' 
test.member1(11) 

print '\n====member2====' 
test.member2(22) 

print '\n====free1====' 
free1(11) 

print '\n====free2====' 
free2(22) 

Çıktı:

decorator1 decoratoring: <function member1 at 0x3aba30> 
decorator2 decoratoring: <function member2 at 0x3ab8b0> 
WrapperClass.__init__ function=<function member2 at 0x3ab8b0> dec_param=456 
decorator1 decoratoring: <function free1 at 0x3ab9f0> 
decorator2 decoratoring: <function free2 at 0x3ab970> 
WrapperClass.__init__ function=<function free2 at 0x3ab970> dec_param=456 

====member1==== 
wrapper((<__main__.Test object at 0x3af5f0>, 11)) dec_param=123 
Test.member1(<__main__.Test object at 0x3af5f0>, 11) 

====member2==== 
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af590>, (22,)) dec_param=456 
Test.member2(22, 2)  <<<- Badness HERE! 

====free1==== 
wrapper((11,)) dec_param=123 
free1(11) 

====free2==== 
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af630>, (22,)) dec_param=456 
free2(22) 
+1

Soruyu yeniden adlandırmanızı tavsiye ederim. Bu aslında dekoratörlerle ilgili değildir, ancak bir işlev nesnesini bir sınıf yöntemi olarak eklemekten ziyade – Casebash

+0

Genel olarak (her zaman olmasa da), bir soru bu kadar uzun olduğunda sorunu izole ederek basitleştirilebilir. Örneğin, sınıfa el ile not eklemeyi denemiş olsaydınız, bunun dekoratörlerle hiçbir ilgisi olmadığını fark edersiniz ve muhtemelen bu kodun tamamını yazmanız daha hızlı olurdu. – Casebash

cevap

10

Sizin WrapperClass ihtiyacı olduğu bir açıklayıcısı (! Bir fonksiyondur gibi), diğer bir deyişle, tedarik uygun özel yöntemler __get__ ve __set__ şifre miktarına üzüldüm. This how-to guide, bu konuda bilmeniz gereken her şeyi açıklar! -)