At 04:32 AM 6/1/03 -0400, Raymond Hettinger wrote: >In the spirit of Michele Simionato's write-up on method resolution order, >I've written up almost everything I know about >descriptors: >http://tinyurl.com/d63d > >Key features: >* Defines a descriptor >* Shows the protocol and how it is called >* Shows a handmade descriptor >* Then covers functions, properties, static and class methods >* Gives examples of each >* Suggests when each would be useful >* Gives a pure python definition of each >* Provides exact references into C source to save efforts in hunting down >details > >I would like to hammer this into something really useful. So, any and all >suggestions are welcome. It would be a good idea to add some information about "data" and "non-data" descriptors, and the differences of how their attribute lookup is processed. I recently posted here about the "attribute lookup process" or something to that effect, which covered this. Understanding data vs. non-data descriptors is important if you want to do pretty much anything with descriptors beyond what property() does. This section: "Alternatively, a descriptor is invoked automatically upon attribute access. For example, obj.a looks up a in the dictionary of obj. If obj defines the method __get__, then it is automatically invoked if obj is a new style class or object." isn't accurate. I think you meant to say that if 'a' defines __get__, then it's invoked. But this isn't accurate either. If obj.__dict__ has an 'a' entry, and the descriptor is a non-data descriptor, __get__ will be ignored and the contents of obj.__dict__ will be returned. (One interesting effect of this is that you can create a non-data descriptor with a __get__ that performs a computation and stashes the result in the instance dictionary - from then on the computed value is returned.) The Python code you have for the algorithm is also incorrect. Here's a more accurate depiction of the process. It's not a straight translation of PyGeneric_GetAttr, but an attempt to do as you have done, i.e. write a pure Python __getattribute__ with equivalent semantics. def __getattribute__(self, key): dict = object.__getattribute__(self, '__dict__') try: # Does the class have a descriptor for this attribute? descr = getattr(type(self),key) except AttributeError: # No, just use what's in the dictionary try: return dict[key] except KeyError: raise AttributeError if hasattr(descr,'__set__') and hasattr(descr,'__get__'): # It's a data descriptor, so use the get method return descr.__get__(self,type(self)) # non-data descriptor, use __dict__ first, *then* __get__ try: return dict[key] except KeyError: if hasattr(descr, '__get__'): return descr.__get__(self, type(self)) # not a descriptor, return it as-is return descr As you can see, it's a bit more complex than your writeup implies. :)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4