Capturing an external modification of a python mutable object serving as an instance class variable

I am trying to track the external modification of records of a python mutable object (like list dictionary). This ability is especially useful in the following two situations:

1) If you want to avoid assigning unwanted values ​​to a python mutable object. Here is a simple example where x should only be a list of integers:

class foo(object):
    def __init__(self,x):
        self.x = x
    def __setattr__(self,attr_name,attr_value):
        # x must be a list of integers only
        if attr_name == 'x' and not isinstance(attr_value,list):
            raise TypeError('x must be a list!')
        elif attr_name == 'x' and len([a for a in attr_value if not isinstance(a,int)]) > 0:
            raise TypeError('x must be a list of integers only')
        self.__dict__[attr_name] = attr_value

# The following works fine and it throws an error because x has a non-integer entry
f = foo(x = ['1',2,3])

# The following assigns an authorized list to x
f = foo(x = [1,2,3])

# However, the following does not throw any error. 
#** I'd like my code to throw an error whenever a non-integer value is assigned to an element of x
f.x[0] = '1'
print 'f.x = ',f.x

2) When you need to update a number of other variables after changing a mutable Python object. Here is an example where x is a dictionary, and x_valsneeds to be updated whenever any changes (for example, deleting a record or assigning a new value for a specific key) are made in x:

class foo(object):
    def __init__(self,x,y = None):
        self.set_x(x)
        self.y = y

    def set_x(self,x):
        """
        x has to be a dictionary 
        """
        if not isinstance(x,dict):
            raise TypeError('x must be a dicitonary')

        self.__dict__['x'] = x
        self.find_x_vals()

    def find_x_vals(self):
        """
        NOTE: self.x_vals needs to get updated each time one modifies x 
        """ 
        self.x_vals = self.x.values()

    def __setattr__(self,name,value):
        # Any Changes made to x --> NOT SURE HOW TO CODE THIS PART! #
        if name == 'x' or ...:
            raise AttributeError('Use set_x to make changes to x!')
        else:
            self.__dict__[name] = value 

if __name__ == '__main__':
    f = foo(x={'a':1, 'b':2, 'c':3}, y = True)
    print f.x_vals

    # I'd like this to throw an error asking to use set_x so self.x_vals
    # gets updated too
    f.x['a'] = 5

    # checks if x_vals was updated
    print f.x_vals

    # I'd like this to throw an error asking to use set_x so self.x_vals gets updated too
    del f.x['a']
    print f.x_vals
+4
2

property, , , , property get ing, set ing delete ING , .

, dict ( , dict) . __getitem__, __setitem__ __delitem__.


- - property __getattribute__ 1 : , , , .

:

  • , , ( )

  • , .

:

class Gateway():
    "use this to wrap an object and provide restrictions to it data"

    def __init__(self, obj, valid_key=None, valid_value=None):
        self.obj = obj
        self.valid_key = valid_key
        self.valid_value = valid_value

    def __setitem__(self, name, value):
        """
        a dictionary can have any value for name, any value for value
        a list will have an integer for name, any value for value
        """
        valid_key = self.valid_key
        valid_value = self.valid_value
        if valid_key is not None:
            if not valid_key(name):
                raise Exception('%r not allowed as key/index' % type(name))
        if valid_value is not None:
            if not valid_value(value):
                raise Exception('%r not allowed as value' % value)
        self.obj[name] = value

:

huh = Gateway([1, 2, 3], valid_value=lambda x: isinstance(x, int))
huh[0] = '1'

Traceback (most recent call last):
 ...
Exception: '1' not allowed as value

Gateway, , append ( list).


1 __getattribute__ , , . .

+1

x_vals , :

@property
def x_vals(self):
    return self.x.values()

x_vals , . , , x.

x_vals , .

+1

Source: https://habr.com/ru/post/1621137/


All Articles