Написать функцию,Stat() которая умеет выполнять две роли:
С одним параметром Stat(класс) — работает как декоратор класса
- Добавляет в объекты класса сбор статистики по всем полям данных
упомянутым в самом классе (т. е. встречающимся в vars(класс))
имя которых не начинается с "_"
По всем остальным атрибутам (методам, спецметодам и т. п., а так же атрибутам, динамически добавленным в __init__() и других методах) статистика не ведётся
- Добавляет в объекты класса сбор статистики по всем полям данных
С двумя параметрами Stat(объект, "поле") — выводит статистику использования поля поле: два целых числа (количество чтений, количество записей)
объект — экземпляр класса, декорированного с помощью Stat
поле — поле этого класса
- Если статистика по данному полю не ведётся, или поля не существует, обя значения равны 0
Экземпляр класса инициализируется с помощью __init__(), т. е. класс не является потомком встроенного класса, не переопределяет __new__(), __getattribute__() и т. п., изначально не содержит слотов/дескрипторов.
1 @Stat
2 class C:
3 A, B = 3, 4
4 def __init__(self, a=None):
5 if a:
6 self.A = a
7
8 c, d = C(), C(123)
9 print(Stat(c, "A"), Stat(d, "A"))
10 d.A = c.A * 2 + c.B
11 c.B = d.A - 1 - len([d.B, d.B, d.B])
12 print(Stat(c, "A"), Stat(c, "B"))
13 print(Stat(d, "A"), Stat(d, "B"))
14 print(Stat(c, "Foo"))
- Подсказка. Я делал так:
- Изготавливал унаследованный класс (возможно, это не обязательно, и можно модифицировать прямо исходный)
Прямо в классе составлял словарь полей, за которыми надо следить (да-да, внутри определения класса вы можете писать любой код, не только A = 1 ☺) и их значений
Прямо в классе подменял все эти поля property-ями, примерно так: setattr(cls, attr, property(getter, setter))
- При этом getter и setter для каждого поля изготавливается всякий раз заново
В __init__()-е объекта делал копию хранилища имён/значений и заводил пустой счётчик (к ним будут ходить все getterы и setterы)
- Тизер, он же спойлер (строки в нём длинные, можно было сделать и поизящнее, но зато он совсем короткий):
(0, 0) (0, 1) (1, 0) (1, 1) (1, 2) (3, 0) (0, 0)