Add post behavior to python's assignment (=) operator

103 views Asked by At

I'm working with a redis database and I'd like to integrate my prototype code to my baseline as seamlessly as possible so I'm trying to bury most of the inner workings with the interface from the python client to the redis server code into a few base classes that I will subclass throughout my production code.

I'm wondering if the assignment operator in python = is a callable and whether if it possible to modify the callable's pre and post behavior, particularly the post behavior such that I can call object.save() so that the redis cache would be updated behind the scenes without having to explicitly call it.

For example,

# using the redis-om module
from redis_om import JsonModel

kwargs = {'attr1': 'someval1', 'attr2': 'someval2'}
jsonModel = JsonModel(**kwargs)

# as soon as assignment completes, redis database 
# has the new value updated without needing to 
# call jsonModel.save()
jsonModel.attr1 = 'newvalue' 
1

There are 1 answers

4
Stanislav Ivanov On

You can make such things with proxy class through __getattr__ and __setattr__ methods:

class ProxySaver:
    def __init__(self, model):
        self.__dict__['_model'] = model

    def __getattr__(self, attr):
        return getattr(self._model, attr)

    def __setattr__(self, attr, value):
        setattr(self._model, attr, value)
        self._model.save()

p = ProxySaver(jsonModel)
print(p.attr1)
p.attr1 = 'test'

But if attributes has a complex types (list, dict, objects, ... ), assignment for nested objects will not been detected and save call will be skipped (p.attr1.append('test'), p.attr1[0] = 'test2').