Украсить методы для каждого экземпляра в Python - PullRequest
5 голосов
/ 15 июня 2011

Предположим, у меня есть некоторый простой класс

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

Я бы хотел украсить метод doSomething, например, для подсчета количества вызовов

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)

Теперь это подсчитываетколичество вызовов к оформленному методу, однако я хотел бы иметь счетчик для каждого экземпляра, чтобы после

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

foo1.doSomething.count было 1, а foo2.doSomething.count было 0. Из того, что я понимаю, этоневозможно с помощью декораторов.Есть ли способ добиться такого поведения?

Ответы [ 2 ]

10 голосов
/ 15 июня 2011

Используйте тот факт, что self (то есть объект, для которого вызывается метод) передается методу в качестве параметра:

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

В приведенном выше коде мы перехватываем объект как obj параметр оформленной версии метода.Использование декоратора довольно просто:

class Foo(object):
    @counted
    def do_something(self): pass
1 голос
/ 15 июня 2011

Не будет ли первый элемент *args объектом, к которому вызывается метод? Вы не можете просто хранить там счет?

...