Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
508 views
in Technique[技术] by (71.8m points)

python - Look up an attribute from an instance

From Python in a Nutshell

Getting an attribute from an instance

When you use the syntax x.name to refer to an attribute of instance x of class C , the lookup proceeds in three steps:

  1. When name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v (i.e., type(v) supplies methods __get__ and __set__ )

    ? The value of x.name is the result of type(v).__get__(v, x, C)

  2. Otherwise, when name is a key in x.__dict__

    ? x.name fetches and returns the value at x.__dict__['name']

  3. Otherwise, x.name delegates the lookup to x’s class (according to the same two-step lookup used for C.name, as just detailed)

    ? When a descriptor v is found, the overall result of the attribute lookup is, again, type(v).__get__(v, x, C)

    ? When a nondescriptor value v is found, the overall result of the attribute lookup is just v

When these lookup steps do not find an attribute, Python raises an AttributeError exception. However, for lookups of x.name , when C defines or inherits the special method __getattr__ , Python calls C.__getattr__(x,'name') rather than raising the exception. It’s then up to __getattr__ to either return a suitable value or raise the appropriate exception, normally AttributeError .

  1. Are step 1 and the first part of step 3 the same? If yes, why does the same step appear twice?

  2. Do they both happen "when name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v"?


__getattribute__(self, name) 

At every request to access attribute x.y, Python calls x.__getattribute__('y'), which must get and return the attribute value or else raise AttributeError. The normal semantics of attribute access (using x.__dict__, C.__slots__, C’s class attributes, x.__getattr__) are all due to object.__getattribute__. When class C overrides __getattribute__, it must implement all of the attribute access semantics it wants to offer. Most often, the most convenient way to implement attribute access semantics is by delegating (e.g., calling object.__getattribute__(self, ...) as part of the operation of your override of __getattribute__).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Are step 1 and the first part of step 3 the same? If yes, why the same step appear twice?

Step 1 requires both __get__ and __set__ (although actually, either __set__ or __delete__ along with __get__ would trigger it). Step 3 happens unconditionally if the attribute isn't found through steps 1 or 2.

Do they both happen "when name is found in C (or in one of C’s ancestor classes) as the name of an overriding descriptor v"?

No. An "overriding descriptor" triggers step 1; another kind of descriptor or a non-descriptor will only be considered in step 3. (The official Python docs don't use the term "overriding descriptor"; they refer to a descriptor with __set__ or __delete__ as a "data descriptor", and if a data descriptor has __get__, the __get__ will take priority over an object found in an instance dict.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...