Here are two options:
First, you could use __slots__
, which will restrict your class to a specific set of attributes.
Not exactly what you want (and slots weren't designed for this in the first place!), but close-ish:
class A(object):
__slots__ = ["a"]
a = A()
a.a = 1 # Will work
a.b = 2 # Will not work
Second, you could override __setattr__
, and have it look up a flag to prevent creating new attributes after init has completed:
class A(object):
__frozen__ = False
def __init__(self, a):
self.a = a
self.__frozen__ = True # At this point no more changes can be made
def __setattr__(self, attr, value):
if self.__frozen__ and not hasattr(self, attr):
raise Exception("New attributes cannot be added!") # Create your own Exception subclass for this
super(A, self).__setattr__(attr, value)
a = A(1)
a.a = 2 # Works
a.b = 2 # Throws an Exception
This is closer to what you want. However, you should think hard about whether this is actually desirable. Is this the best way to avoid mistakes? Maybe you'd want to e.g. write tests instead?
Among other things, this will break subclassing if your subclass calls super(TheSubClass, self).__init__(*args, **kwargs)
and then tries to access an attribute.