Форум сайта python.su
Идея простая. Сдаются классы по сценарию одного металасса. У каждого экземпляра есть с рождения флажок changed = False.
В каждый этот класс при создании запихивается вловарь данных, что вревращает объект в отражение полученного словаря dic.
def __init__(self, dic):
self.__dict__=dic
В определённые моменты мне надо знать, были ли изменения в хотя бы 1 аттрибуте или нет.
Видел шикарный видеопример как можно повесить счётчик на каждый метод https://www.youtube.com/watch?v=tZnBtoJoD-o
Т.к. данных в самом классе нет, я в __new__ добавляю только changed = False, остальное ожидаю увидеть в __call__. И вижу. Но одно дело сделать декоратор для метода, а другое - свойство со спрятанной функцией. Что-то вроде дескриптора. Здесь я повис. Если я сначала создаю обычное свойство и после него пытаюсь приравнять ему значение, он стирает всё свойство и добавляет значение.
Делаю например так
def __call__(self, *args, **kwargs):
obj= type.__call__(self, *args, **kwargs)
def _getter(self):
return self.Login
def _setter(self, val):
self.changed=True
self.Login = val
def _deleter(self):
del self.Login
for item, value in obj.__dict__.items():
obj.__dict__.update({item : property(_getter, _setter, _deleter)})
здесь свойство
obj.__dict__=value
здесь свойства уже нет
естественно сами функции дейсриптора нерабочие. Речь пока не о них
Может есть какой универсальный способ реакции на изменение объекта? В джанго всё просто, берёшь и ловишь сигнал.
Я честно признают, что у меня полная каша в голове от getattr, __get__, __getattr__, __getattribute__. Это какой-то ужас, не могу разобраться когда что вызывается.
Отредактировано Dariloff (Март 23, 2014 18:20:09)
Офлайн
class Cls: def __init__(self, dic): self.__dict__ = dic watched = set(dic.keys()) self.changed = False def __setattr__(self, slot, value): if slot in watched: self.changed = True super().__setattr__(slot, value) Cls.__setattr__ = __setattr__
Офлайн
Работает для класса. В метаклассе __init__ не видит переданный ему словарь. Классов таких 4. Хочется одним метаклассом описать их поведение. В любом случае спасибо большое!
Офлайн
Всё! Сделал через __call__ метакласса.
Ещё раз спасибо! Продолжаю достигать дзена.
Результат
class Meta ( type ): def __call__(self, load=None, *args, **kwargs): obj = type.__call__(self, *args, **kwargs) if 'ready' in kwargs: obj.__dict__.update(kwargs['ready']) watched = set(kwargs['ready'].keys()) obj.changed = False def __setattr__(obj, slot, value): if slot in watched: obj.changed = True super(obj.__class__, obj).__setattr__(slot, value) obj.__class__.__setattr__ = __setattr__ return obj
Отредактировано Dariloff (Март 23, 2014 22:03:14)
Офлайн
для количества экземпляров > 1 правильно работает? А то я ошибся там
Офлайн
Теперь правильно. Ещё раз подправил. Ато до этого работало т.к. забыл в самом классе стереть механизм.
Офлайн