Найти - Пользователи
Полная версия: регистрация изменений свойств множества экземпляров классов.
Начало » Python для экспертов » регистрация изменений свойств множества экземпляров классов.
1
Dariloff
Идея простая. Сдаются классы по сценарию одного металасса. У каждого экземпляра есть с рождения флажок 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__. Это какой-то ужас, не могу разобраться когда что вызывается.
sergeek
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__
Dariloff
Работает для класса. В метаклассе __init__ не видит переданный ему словарь. Классов таких 4. Хочется одним метаклассом описать их поведение. В любом случае спасибо большое!
Dariloff
Всё! Сделал через __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
Ходил вокруг, да около весь день.
sergeek
для количества экземпляров > 1 правильно работает? А то я ошибся там
Dariloff
Теперь правильно. Ещё раз подправил. Ато до этого работало т.к. забыл в самом классе стереть механизм.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB