The same could be applied to the globals if module subclassing were practical.  Then you could just use descriptors on that subclass.  I expect that custom import functionality could provide this right now.  Naturally, this would affect that promise Nick was talking about regarding globals, which could be confusing.  But only in the same way that descriptors can be for classes already.<div>
<br></div><div>Even if messing with the module class's __dict__ were legal, adding decorators there would probably not be effective since all modules would get those attributes.  However, with module subclasses that would be more practical.</div>
<div><br></div><div>Of course, the application of all this would be to let a module control what happens when another module tries to use the first module's namespace.  But that is what descriptors are all about.</div>
<div><br></div><div>-eric<br><br><div class="gmail_quote">On Wed, Mar 30, 2011 at 2:26 PM, Raymond Hettinger <span dir="ltr"><<a href="mailto:raymond.hettinger@gmail.com">raymond.hettinger@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im"><br>
On Mar 29, 2011, at 10:59 AM, Eric Snow wrote:<br>
<br>
> Here's another outlandish idea.  How about if descriptors could be used outside of classes.  I.e. any global or local variable could be assigned a descriptor object and the descriptor protocol would be respected for that variable.  This would be a pretty messy change, and I have no illusions that the idea will go anywhere.  However, would there be room for this in python?<br>

<br>
</div>FWIW, you can already do this with locals (am not saying you should do it, am just saying that you can do it).<br>
<br>
Remember, the essential mechanism for descriptors is in the lookup function, not in the descriptor itself.  For example, property() objects are descriptors only because they define one of the descriptor protocol methods (__get__, et al).  Whether it gets invoked solely depends on how you look it up.   If you use regular dictionary lookup, a.__class__.__dict__['x'], then the property object is retrieved but no special action occurs.  If you use dotted lookup, a.x, then the property's __get__ method is called.  This is because the lookup function, object.__getattribute__(), has code to detect and invoke descriptors.<br>

<br>
A ultra-simplified version of the lookup functions's psuedo-code looks like this:<br>
<br>
          value = kls.__dict__[key]<br>
          if hasattr(value, '__get__'):<br>
                return call_the_getter(kls ,key)<br>
          else:<br>
                return the value<br>
<br>
Knowing this, it is possible to emulate that behavior with a dictionary whose lookup function, __getitem__(), can detect and invoke some sort of descriptor protocol.<br>
<br>
Since eval/exec can use arbitrary mappings for locals, you can use your custom dictionary while executing arbitrary python code.  Essentially, you're executing python code in an environment where the lookup function for locals has been trained to handle your custom descriptor protocol.<br>

<br>
<br>
Raymond<br>
<br>
<br>
----- simple example -----<br>
<br>
class MyDict:<br>
    def __init__(self, mapping):<br>
        self.mapping = mapping<br>
    def __getitem__(self, key):<br>
        value = self.mapping[key]<br>
        if hasattr(value, '__get__'):<br>
            print('Invoking descriptor on', key)<br>
            return value.__get__(key)<br>
        print('Getting', key)<br>
        return value<br>
    def __setitem__(self, key, value):<br>
        self.mapping[key] = value<br>
<br>
class Property:<br>
    def __init__(self, getter):<br>
        self.getter = getter<br>
    def __get__(self, key):<br>
        return self.getter(key)<br>
<br>
if __name__ == '__main__':<br>
    md = MyDict({})<br>
    md['x'] = 10<br>
    md['_y'] = 20<br>
    md['y'] = Property(lambda key: md['_'+key])<br>
    print(eval('x+y+1', {}, md))<br>
<br>
<br>
<br>
</blockquote></div><br></div>