全局作用域中的描述符?

2 投票
2 回答
806 浏览
提问于 2025-04-16 03:11

在Python 2.6中,描述符协议只适用于类的定义,所以只能通过类的实例来使用。

有没有类似的方式可以用来控制全局变量的获取和设置呢?

我想加快一个模块的导入速度,这个模块需要和主机系统进行交互,因此需要进行一些比较耗时的探测操作。探测的结果会存储在一个模块的全局变量中,这个全局变量在导入时就会被初始化;所以我想把这个初始化的时间推迟到绝对需要的时候。

请不要评论全局变量是多么糟糕。我知道它们是什么,也知道什么时候该用。

我现在的计划是创建一个全局实例,使用描述符,并把我现在的所有全局变量都放到这个实例的属性里。我觉得这样可行;我只是想问问有没有其他的方法。

2 个回答

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))

虽然有点麻烦,但我觉得这个方法非常酷。

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这个装饰器,你可以大大简化上面的代码。

撰写回答