pythonpython-3.xclassooppython-datamodel

Prevent creating new attributes outside __init__


I want to be able to create a class (in Python) that once initialized with __init__, does not accept new attributes, but accepts modifications of existing attributes. There's several hack-ish ways I can see to do this, for example having a __setattr__ method such as

def __setattr__(self, attribute, value):
    if not attribute in self.__dict__:
        print "Cannot set %s" % attribute
    else:
        self.__dict__[attribute] = value

and then editing __dict__ directly inside __init__, but I was wondering if there is a 'proper' way to do this?


Solution

  • I wouldn't use __dict__ directly, but you can add a function to explicitly "freeze" a instance:

    class FrozenClass(object):
        __isfrozen = False
        def __setattr__(self, key, value):
            if self.__isfrozen and not hasattr(self, key):
                raise TypeError( "%r is a frozen class" % self )
            object.__setattr__(self, key, value)
    
        def _freeze(self):
            self.__isfrozen = True
    
    class Test(FrozenClass):
        def __init__(self):
            self.x = 42#
            self.y = 2**3
    
            self._freeze() # no new attributes after this point.
    
    a,b = Test(), Test()
    a.x = 10
    b.z = 10 # fails