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?
When we design a class, we can use slots to prevent the dynamic creation of attributes. To define slots, you have to define a list with the name __slots__ . The list has to contain all the attributes, you want to use.
It is perfectly possible for instance attributes to be defined outside of your __init__ , you need to be careful about how your class is used.
__slots__ is a class variable. If you have more than one instance of your class, any change made to __slots__ will show up in every instance. You cannot access the memory allocated by the __slots__ declaration by using subscription. You will get only what is currently stored in the list.
The __init__ method is the Python equivalent of the C++ constructor in an object-oriented approach. The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With