2010-08-23 3 views
2

descriptor protocol в Python 2.6 определен только для определений классов и, следовательно, может использоваться только экземплярами.Дескрипторы в глобальном масштабе?

Есть ли какой-то эквивалент для инструмента получения/набора глобальных переменных?

Я пытаюсь ускорить импорт модуля, который взаимодействует с главной системой, и, как таковой, должен выполнить некоторое дорогое исследование хоста. Результаты (дорогостоящего) зонда хранятся в глобальном модуле, который инициализируется во время импорта; поэтому я пытаюсь отложить инициализацию до полной необходимости.

Пожалуйста, никаких комментариев о том, что глобалы являются злыми. Я знаю, что это такое и когда их использовать.

Мой текущий план - создать глобальный экземпляр, который использует дескрипторы, и переместить все мои текущие глобальные переменные в атрибуты этого экземпляра. Я ожидаю, что это сработает; Я просто спрашиваю, есть ли другой способ.

+1

Возможно (хотя я и не рекомендовал бы это) подкласса 'module', добавить необходимые дескрипторы, создать экземпляр подкласса и заменить запись' sys.modules' текущего модуля новым экземпляром, все в модуле собственный файл. – kwatford

ответ

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

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

Хотя немного громоздкий, я думал, что это было очень круто.

Смежные вопросы