type.__setattr__
is used for classes, basically instances of metaclasses. object.__setattr__
on the other hand, is used for instances of classes. This is totally understood.
I don't see a significant difference between the two method, at least at Python level, I notice the two use the same procedures for attribute assignment, correct me if I'm wrong:
Suppose a
is an instance of a user-defined class, just a normal class:
class A:
pass
a = A()
a.x = ...
then a.x = ..
invokes type(a).__setattr__(...)
which performs the following steps:
Note: type(a).__setattr__
will find __setattr__
in object
builtin class
1) Look for a data descriptor in type(a).__mro__
.
2) If a data descriptor was found, call its __set__
method and exit.
3) If no data descriptor was found in type(a).__mro__
, then add attribute to a.__dict__
, a.__dict__['x'] = ...
With classes--instances of metaclasses, the process is similar:
class A(metaclass=type):
pass
then: A.x = ...
is translated to type(A).__setattr__(...)
which performs the following steps:
Note: type(A).__setattr__
will find __setattr__
in type
builtin class
1) Look for a data descriptor in type(A).__mro__
2) If a data descriptor was found, call its __set__
method and exit.
3) If no data descriptor was found in type(A).__mro__
, then add attribute to A.__dict__
, a.__dict__['x'] = ...
But object.__setattr__
doesn't work for classes:
>>> object.__setattr__(A, 'x', ...)
TypeError: can't apply this __setattr__ to type object
and vice versa, type.__setattr__
doesn't work for instances of A
:
>>> type.__setattr__(A(), 'x', ...)
TypeError: descriptor '__setattr__' requires a 'type' object but received a 'A'
Hmmm! There must be something different between the two methods. This is subtle, but true nonetheless!
Presumably the two methods perform the same steps inside __setattr__
, what is the difference between type.__setattr__
and object.__setattr__
so that type.__setattr__
is limited to classes and object.__setattr__
is limited to instances of classes?