Форум сайта python.su
Привет,
дочитываю книгу М. Лутца “Изучаем Python” и пришла в голову идея создать декоратор класса, который подсчитывает кол-во созданных экземпляров.
Реализовать задачу полностью не удалось, вот что получилось:
def count(aClass): aClass.numInstances = 0 class Wrapper(aClass): def __init__(self, *args, **kargs): aClass.numInstances += 1 aClass.__init__(self, *args, **kargs) return Wrapper if __name__ == '__main__': @count class Spam(): def __init__(self): print('in Super.method') def printerS(self): print('blablabla') @count class Sub(Spam): pass @count class Other(Spam): def printer(self): print('lalala') x = Spam() y1, y2 = Sub(), Sub() z1, z2, z3 = Other(), Other(), Other() print(x.numInstances, y1.numInstances, z1.numInstances) print(Spam.numInstances, Sub.numInstances, Other.numInstances)
in Super.method
in Super.method
in Super.method
in Super.method
in Super.method
in Super.method
6 2 3
6 2 3
Отредактировано WoMax (Май 27, 2014 14:46:22)
Офлайн
Удали строчку
aClass.__init__(self, *args, **kargs)
Отредактировано MindHatter (Май 26, 2014 17:17:38)
Офлайн
Уже пробовал)
Тогда подклассы Sub, Other не унаследует __init__ от Spam и не будет выводится строка “in Super.method” либо другие аргументы со значениями по умолчанию если таковые будут в __init__ суперклассa Spam. :-/
Отредактировано WoMax (Май 26, 2014 17:28:28)
Офлайн
from functools import wraps def instance_counter(cls): @wraps(cls) def wrapper(*args, **kwargs): wrapper.counter += 1 return cls(*args, **kwargs) wrapper.counter = 0 return wrapper @instance_counter class Foo(object): def __init__(self): print("Foo init") print(Foo.counter) foo = Foo() foo1 = Foo() print(Foo.counter)
Офлайн
Спасибо, прочитал что такое “wraps”)
Однако с моим проверочным кодом ругается(((
from functools import wraps def instance_counter(cls): @wraps(cls) def wrapper(*args, **kwargs): wrapper.counter += 1 return cls(*args, **kwargs) wrapper.counter = 0 return wrapper if __name__ == '__main__': # проверочный код @instance_counter class Spam(): def __init__(self): print('in Super.method') def printerS(self): print('blablabla') @instance_counter class Sub(Spam): pass @instance_counter class Other(Spam): def printer(self): print('lalala') x = Spam() y1, y2 = Sub(), Sub() z1, z2, z3 = Other(), Other(), Other() print(Spam.counter , Sub.counter , Other.counter) z3.printer() z3.printerS()
C:\Users\Максим>C:\Python33\Modules\countEX3.py Traceback (most recent call last): File "C:\Python33\Modules\countEX3.py", line 19 in <module> class Sub(Spam): pass TypeError: function() argument 1 must be code not str
Отредактировано WoMax (Май 26, 2014 23:54:24)
Офлайн
Так понимаю, декоратор instance_counter возвращает обернутую функцию вместо обернутого класса, поэтому интерпретатор ругается.
Отредактировано WoMax (Май 27, 2014 14:45:08)
Офлайн
def count(aClass): aClass.numInstances = 0 class Wrapper(aClass): def __init__(self, *args, **kargs): if self.__class__ == Wrapper: aClass.numInstances += 1 aClass.__init__(self, *args, **kargs) return Wrapper
Офлайн
И забудь в python про табуляции. Замени все табы на четыре пробела.
Офлайн
Найс! Как раз тоже думал, что необходима проверка if, но никак не мог сообразить как именно прописать условие.
Спасибо)
Офлайн