[Python-ideas] The Descriptor Protocol...

Martin Chilvers martin.chilvers at gmail.com
Wed Mar 2 10:05:11 CET 2011


G'day!

Please excuse me if I have missed something obvious, but I have a 
question about the implementation of the descriptor protocol, and more 
specifically about the arguments passed to the '__get__' and '__set__' 
methods.

According to Raymond Hettinger's "How-To Guide for Descriptors" at:-

http://users.rcn.com/python/download/Descriptor.htm#invoking-descriptors

The *pseudo* implementation of __getattribute__ is as follows:-

def __getattribute__(self, key):
     "Emulate type_getattro() in Objects/typeobject.c"
     v = object.__getattribute__(self, key)
     if hasattr(v, '__get__'):
        return v.__get__(None, self)
     return v

As mentioned above, this is obviously only pseudo-Python, but it serves 
to illustrate my question which is, why isn't the 'key' argument passed 
through to the '__get__' (and similarly, '__set__') methods?

In seems to me that:-

1) In terms of API design/information flow through '__getattribute__' it 
feels like we 'drop' the 'key' when we call call a descriptor's 
'__get__' method. In other words, if '__getattribute__' gets to use the 
key when working out what to return it also seems natural to give the 
descriptor the same information.

2) It makes the implementation of some descriptor based tools much 
uglier. Take for example a type specification tool, we might have 
something like:-

class Person(object):
     name    = Str()
     address = Str()

where 'Str' is a descriptor. It would be nice to know in the '__get__' 
and '__set__' methods of 'Str' which attribute is being accessed. Of 
course, I can get around this by either:-

a) using a metaclass to harvest the descriptors and set the attribute 
name. This is fine, but:-
   - it forces me to use a metaclass ;^)
   - it means that I can't share descriptors because they are bound to
     a particular attribute name which has obvious scaleability
     implications.

b) make the developer duplicate the attribute name when constructing the 
descriptor:-

class Person(object):
     name    = Str('name')
     address = Str('address')

which, well, just smells, and conflicts with step 3 of TDD ;^)

Again, apologies if I've missed the obvious - I've trawled the usual 
places and not found this mentioned anywhere...

Thanks folks!

Martin





More information about the Python-ideas mailing list