2011-06-15 10 views
5

Załóżmy Mam prostą klasęDekoracje metody na przykład w Pythonie

class TestClass: 
    def doSomething(self): 
     print 'Did something' 

chciałbym ozdobić metodę doSomething, na przykład policzyć liczbę połączeń

class SimpleDecorator(object): 
    def __init__(self,func): 
     self.func=func 
     self.count=0 
    def __get__(self,obj,objtype=None): 
     return MethodType(self,obj,objtype) 
    def __call__(self,*args,**kwargs): 
     self.count+=1 
     return self.func(*args,**kwargs) 

Teraz ten zlicza liczba wywołań do metody dekorowanej, jednak chciałbym mieć licznik na wystąpienie, taki, że po

foo1=TestClass() 
foo1.doSomething() 
foo2=TestClass() 

foo1.doSomething.count to 1, a foo2.doSomething.count to 0. Z tego co rozumiem, nie jest to możliwe przy użyciu dekoratorów. Czy jest jakiś sposób na osiągnięcie takiego zachowania?

Odpowiedz

10

Wykorzystaj fakt, że self (czyli przedmiot którym metoda jest wywoływana na) jest przekazywana jako parametr do metody:

import functools 

def counted(method): 
    @functools.wraps(method) 
    def wrapped(obj, *args, **kwargs): 
     if hasattr(obj, 'count'): 
      obj.count += 1 
     else: 
      obj.count = 1 
     return method(obj, *args, **kwargs) 
    return wrapped 

W powyższym kodzie przechwycenia obiektu jako obj parametr urządzone wersja metody. Używanie dekoratora jest dość proste:

class Foo(object): 
    @counted 
    def do_something(self): pass 
1

Czy pierwszy element obiektu *args nie byłby przedmiotem wywoływanej metody? Nie możesz po prostu zapisać tam liczby?

+0

Tak, myślę, że byłoby to możliwe. Ale wydaje mi się to nieoptymalnym projektem, ponieważ dekorator będzie polegał na właściwościach klasy, z której jest ona używana, co utrudnia jej użycie. – Christoph

Powiązane problemy