开发者

Descriptors in global scope?

The descriptor protocol in Python 2.6 is only defined for class definitions, and thus can only be used by instances.

Is there some equivalent for instrumenting get/set of globals?

I'm trying to speed up the importing of a module which interacts with the host system, and as such has to perform some expensive probing of the host. The results of the (expensive) probe are stored in a module global that is initialized at import time; so I'm trying to delay the initialization until absolutely required.

Please, no comments about globals being evil. I know what they are and when to use them.

My c开发者_运维技巧urrent plan is to create a global instance that uses descriptors, and move all my current globals into the attributes of this instance. I expect this will work; I'm just asking if there's another way.


My current plan is to create a global instance that uses descriptors, and move all my current globals into the attributes of this instance. I expect this will work; I'm just asking if there's another way.

That's precisely what I would do. There is no equivalent to descriptors outside of classes.

The other option, which I have also sometimes used, would be to use a function instead of a variable name, something like this:

_expensive_to_compute = None
def get_expensive_to_compute():
    global _expensive_to_compute
    if _expensive_to_compute is None:
        _expensive_to_compute = do_computation()
    return _expensive_to_compute

If you already have a @memoize decorator defined somewhere, you can simplify the above considerably.


If you really want to do this, this link gives a pretty cool method to implement. The only caveat is you'd have to execute your code using eval/exec/execfile.

https://mail.python.org/pipermail/python-ideas/2011-March/009657.html

class MyDict:
    def __init__(self, mapping):
        self.mapping = mapping
    def __getitem__(self, key):
        value = self.mapping[key]
        if hasattr(value, '__get__'):
            print('Invoking descriptor on', key)
            return value.__get__(key)
        print('Getting', key)
        return value
    def __setitem__(self, key, value):
        self.mapping[key] = value

class Property:
    def __init__(self, getter):
        self.getter = getter
    def __get__(self, key):
        return self.getter(key)

if __name__ == '__main__':   
    md = MyDict({})
    md['x'] = 10
    md['_y'] = 20
    md['y'] = Property(lambda key: md['_'+key])
    print(eval('x+y+1', {}, md))

While a little cumbersome, I thought this was very cool.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜