[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