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.yis not an overriding descriptor, Python usually translatesx.y=zintox.__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.