Note that there are some explanatory texts on larger screens.

plurals
  1. POpython attribute lookup without any descriptor magic?
    primarykey
    data
    text
    <p>I've started to use the python descriptor protocol more extensively in the code I've been writing. Typically, the default python lookup magic is what I want to happen, but sometimes I'm finding I want to get the descriptor object itself instead the results of its <code>__get__</code> method. Wanting to know the type of the descriptor, or access state stored in the descriptor, or somesuch thing.</p> <p>I wrote the code below to walk the namespaces in what I believe is the correct ordering, and return the attribute raw regardless of whether it is a descriptor or not. I'm surprised though that I can't find a built-in function or something in the standard library to do this -- I figure it has to be there and I just haven't noticed it or googled for the right search term.</p> <p>Is there functionality somewhere in the python distribution that already does this (or something similar)?</p> <p>Thanks!</p> <pre><code>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): # get an attribute in the same resolution order one would normally, # but do not call __get__ on the attribute even if it has one obj_dict, class_dicts = namespaces(obj) # look for a data descriptor in class hierarchy; it takes priority over # the obj's dict if it exists for d in class_dicts: if name in d and isdatadescriptor(d[name]): return d[name] # look for the attribute in the object's dictionary if obj_dict and name in obj_dict: return obj_dict[name] # look for the attribute anywhere in the class hierarchy for d in class_dicts: if name in d: return d[name] raise AttributeError </code></pre> <p>Edit Wed, Oct 28, 2009.</p> <p>Denis's answer gave me a convention to use in my descriptor classes to get the descriptor objects themselves. But, I had an entire class hierarchy of descriptor classes, and I didn't want to begin <em>every</em> <code>__get__</code> function with a boilerplate</p> <pre><code>def __get__(self, instance, instance_type): if instance is None: return self ... </code></pre> <p>To avoid this, I made the root of the descriptor class tree inherit from the following:</p> <pre><code>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) </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload