2010-08-23 204 views
2

Python 2.6中的descriptor protocol僅爲類定義定義,因此只能由實例使用。全球範圍內的描述符?

是否有一些等同於檢測全局變量的get/set?

我想加快與主機系統交互的模塊的導入,並且因此必須執行一些主機的昂貴的探測。 (昂貴的)探針的結果存儲在全局模塊中,該模塊在導入時初始化;所以我試圖延遲初始化直到絕對需要。

請不要評論globals是邪惡的。我知道他們是什麼以及何時使用它們。

我目前的計劃是創建一個使用描述符的全局實例,並將所有當前的全局變量移動到此實例的屬性中。我希望這會起作用;我只是問是否有另一種方式。

+1

這是可能的(但我真的不推薦它)子類'模塊',添加所需的描述符,實例化子類,並替換當前模塊的'sys.modules'條目與新實例,所有在模塊自己的文件。 – kwatford 2010-08-23 16:45:22

回答

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裝飾某處定義,你可以大大簡化以上。

+0

我懷疑是這樣。 :) 謝謝。 – RobM 2010-08-23 17:14:16

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

雖然有點麻煩,我認爲這是非常酷。