Python memoising/deferred декоратор свойства поиска

Недавно я прошел существующую кодовую базу, содержащую много классов, где атрибуты экземпляра отражают значения, сохраненные в базе данных. Я осуществил рефакторинг много этих атрибутов, чтобы иметь их поиски базы данных быть задержанным, т.е. не быть инициализированным в конструкторе, но только после первого чтения. Эти атрибуты не переключают время жизни экземпляра, но они - реальное узкое место, чтобы вычислить, что в первый раз и только действительно получил доступ для особых случаев. Следовательно они могут также кэшироваться после того, как они были получены от базы данных (это поэтому соответствует определению memoisation, где вход не является просто "никаким входом").

Я ввожу следующий отрывок кода много раз для различных атрибутов через различные классы:

class testA(object):

  def __init__(self):
    self._a = None
    self._b = None

  @property
  def a(self):
    if self._a is None:
      # Calculate the attribute now
      self._a = 7
    return self._a

  @property
  def b(self):
    #etc

Существует ли существующий декоратор уже, чтобы сделать это в Python, о котором я просто не знаю? Или, существует ли довольно простой способ определить декоратора, который делает это?

Я работаю в соответствии с Python 2.5, но 2,6 ответа могли бы все еще быть интересными, если они существенно отличаются.

Примечание:

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

106
задан detly 23 May 2016 в 01:54
поделиться

2 ответа

Вот пример реализации ленивого декоратора свойств:

import functools

def lazyprop(fn):
    attr_name = '_lazy_' + fn.__name__

    @property
    @functools.wraps(fn)
    def _lazyprop(self):
        if not hasattr(self, attr_name):
            setattr(self, attr_name, fn(self))
        return getattr(self, attr_name)

    return _lazyprop


class Test(object):

    @lazyprop
    def a(self):
        print 'generating "a"'
        return range(5)

Интерактивная сессия:

>>> t = Test()
>>> t.__dict__
{}
>>> t.a
generating "a"
[0, 1, 2, 3, 4]
>>> t.__dict__
{'_lazy_a': [0, 1, 2, 3, 4]}
>>> t.a
[0, 1, 2, 3, 4]
123
ответ дан 24 November 2019 в 03:48
поделиться

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

class lazyproperty(property):
   ....

class testA(object):
   ....
  a = lazyproperty('_a')
  b = lazyproperty('_b')
3
ответ дан 24 November 2019 в 03:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: