全球范围内的描述符?

时间:2010-08-23 16:33:10

标签: python scope descriptor

Python 2.6中的descriptor protocol仅为类定义定义,因此只能由实例使用。

是否有一些等效的仪器获取/设置全局变量?

我正在尝试加速导入与主机系统交互的模块,因此必须执行一些昂贵的主机探测。 (昂贵的)探测器的结果存储在导入时初始化的模块全局中;所以我试图延迟初始化,直到绝对需要。

请不要评论全局变形是邪恶的。我知道它们是什么以及何时使用它们。

我目前的计划是创建一个使用描述符的全局实例,并将所有当前全局变量移动到此实例的属性中。我希望这会奏效;我只想问是否还有另一种方式。

2 个答案:

答案 0 :(得分:2)

  

我目前的计划是创建一个使用描述符的全局实例,并将所有当前全局变量移动到此实例的属性中。我希望这会奏效;我只想问是否还有另一种方式。

这正是我要做的。没有等同于类之外的描述符。

我有时也会使用的另一个选项是使用函数而不是变量名,如下所示:

_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

如果您已在某处定义了@memoize装饰器,则可以大大简化上述步骤。

答案 1 :(得分:1)

如果你真的想这样做,这个链接提供了一个非常酷的方法来实现。唯一需要注意的是,您必须使用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))

虽然有点麻烦,但我觉得这很酷。