According to Python 2.7.12 documentation:
Ifwants to assign to an instance attribute, it should
not simply execute— this would cause a recursive
self.name = value
call to itself. Instead, it should insert the value in the dictionary
of instance attributes, e.g.,. For
self.__dict__[name] = value
new-style classes, rather than accessing the instance dictionary, it
should call the base class method with the same name, for example,
object.__setattr__(self, name, value)
def __setattr__(self, name, val):
self.__dict__[name] = val;
c = Class()
c.val = 42
super(Class, obj).__setattr__(name, value)
New-style classes could be using slots, at which point there is no
__dict__ to assign to. New-style classes also support other data descriptors, objects defined on the class that handle attribute setting or deletion for certain names.
From the documentation on slots:
By default, instances of both old and new-style classes have a dictionary for attribute storage. This wastes space for objects having very few instance variables. The space consumption can become acute when creating large numbers of instances.
The default can be overridden by defining
__slots__in a new-style class definition. The
__slots__declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because
__dict__is not created for each instance.
Access to slots is instead implemented by adding data descriptors on the class; an object with
__set__ and / or
__del__ methods for each such attribute.
Another example of data descriptors are
property() objects that have a setter or deleter function attached. Setting a key with the same name as such a descriptor object in the
__dict__ would be ignored as data descriptors cause attribute lookup to bypass the
object.__setattr__() knows how to handle data descriptors, which is why you should just call that.