Python in a Nutshell describes the lookup procedure when getting an attribute from a class, e.g. cls.name
and the lookup procedure when getting an attribute from an instance, e.g. obj.name
But I am not sure when it comes to setting an attribute:
Setting an attribute
Note that the attribute lookup steps happen as just described only when you refer to an attribute, not when you bind an attribute. When you bind (on either a class or an instance) an attribute whose name is not special (unless a
__setattr__
method, or the__set__
method of an overriding descriptor, intercepts the binding of an instance attribute), you affect only the__dict__
entry for the attribute (in the class or instance, respectively). In other words, for attribute binding, there is no lookup procedure involved, except for the check for overriding descriptors.
My questions are:
What is the "lookup" procedure when setting an attribute from a class, e.g.
cls.name=value
?What is the "lookup" procedure when setting an attribute from an object, e.g.
obj.name=value
?
The procedures seem to involve
the
__setattr__
method__setattr__(self, name, value)
At every request to bind attribute
x.y
(typically, an assignment statementx.y=value
, but also, for example,setattr(x, 'y', value)
), Python callsx.__setattr__('y', value)
. Python always calls__setattr__
for any attribute binding on x—a major diff erence from__getattr__
(__setattr__
is closer to__getattribute__
in this sense). To avoid recursion, whenx.__setattr__
bindsx
’s attributes, it must modifyx.__dict__
directly (e.g., viax.__dict__[name]=value
); even better,__setattr__
can delegate the setting to the superclass (by callingsuper(C, x).__setattr__('y', value)
or, in v3, justsuper().__setattr__('y', value)
). Python ignores the return value of__setattr__
. If__setattr__
is absent (i.e., inherited fromobject
), andC.y
is not an overriding descriptor, Python usually translatesx.y=z
intox.__dict__['y']=z
.the
__set__
method of an overriding descriptor (So I asked Why does `object.__get__` have an argument `owner` for the owner class, while `object.__set__` doesn't?)- the
__dict__
entry for the attribute (in the class or instance, respectively)
Given that the book distinguishes the lookup procedures for getting an attribute from a class and from an instance, it is natural to think that the "lookup" procedures are different when setting an attribute from a class and when setting an attribute from an instance.
But since in Python3, every class object is actually an instance of its metaclass (e.g. type
class), are the "lookup" procedure for setting an attribute from a class and the "lookup" procedure for setting an attribute from an instance really different?
Thanks.