I started using the python descriptor protocol in more detail in the code I wrote. Typically, the default search magic for python is what I want, but sometimes I find that I want to get the handle object itself, and not the results of its __get__ method. Desire to find out the type of descriptor or access state stored in the descriptor, or something similar.
I wrote the code below to skip namespaces in what I think is right and to return the original attribute regardless of whether it is a descriptor or not. I am surprised, although I cannot find a built-in function or something in the standard library to do this - I believe that it should be there, and I just did not notice it or searched for the correct search.
Is there any function in the python distribution that already does this (or something similar)?
Thanks!
from inspect import isdatadescriptor def namespaces(obj): obj_dict = None if hasattr(obj, '__dict__'): obj_dict = object.__getattribute__(obj, '__dict__') obj_class = type(obj) return obj_dict, [t.__dict__ for t in obj_class.__mro__] def getattr_raw(obj, name):
Edited Wed, Oct 28, 2009.
Denis's answer gave me an agreement on using a descriptor in my classes to get the descriptor objects themselves. But I had a whole hierarchy of class descriptor classes, and I did not want to start every __get__ function with a template
def __get__(self, instance, instance_type): if instance is None: return self ...
To avoid this, I made the root of the descriptor class tree inherited from the following:
def decorate_get(original_get): def decorated_get(self, instance, instance_type): if instance is None: return self return original_get(self, instance, instance_type) return decorated_get class InstanceOnlyDescriptor(object): """All __get__ functions are automatically wrapped with a decorator which causes them to only be applied to instances. If __get__ is called on a class, the decorator returns the descriptor itself, and the decorated __get__ is not called. """ class __metaclass__(type): def __new__(cls, name, bases, attrs): if '__get__' in attrs: attrs['__get__'] = decorate_get(attrs['__get__']) return type.__new__(cls, name, bases, attrs)