Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 324
astrofrog Avatar asked Aug 30 '10 19:08

astrofrog


People also ask

How do you prevent dynamic creation of attributes in Python?

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.

Is it OK to define instance attribute outside init?

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.

What is __ slots __ in Python?

__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.

Is __ init __ an attribute?

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.


1 Answers

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 
like image 56
Jochen Ritzel Avatar answered Oct 05 '22 02:10

Jochen Ritzel