I just spent too long on a bug like the following:
>>> class Odp():
def __init__(self):
self.foo = \"bar\"
>>> o = Odp()
>
You can implement a __setattr__
method for the purpose -- that's much more robust than the __slots__
which is often misused for the purpose (for example, __slots__
is automatically "lost" when the class is inherited from, while __setattr__
survives unless explicitly overridden).
def __setattr__(self, name, value):
if hasattr(self, name):
object.__setattr__(self, name, value)
else:
raise TypeError('Cannot set name %r on object of type %s' % (
name, self.__class__.__name__))
You'll have to make sure the hasattr
succeeds for the names you do want to be able to set, for example by setting the attributes at a class level or by using object.__setattr__
in your __init__
method rather than direct attribute assignment. (To forbid setting attributes on a class rather than its instances you'll have to define a custom metaclass with a similar special method).