Наверное все знают зачем эта ленивая инициализация нужна и как, в общем случае, реализуется.
Для тех кто не знает, ниже я попытался, как мог, объяснить как оно работает. А еще ниже, привел пример кода декоратора, который немного упрощает реализацию “ленивой” инициализации в программах на питоне.
Кратко о “ленивой” инициализации.
Предположим, что у нас имеется некий объект класса A, в процессе работы этому объекту, для его внутренних нужд, может понадобится экземпляр класса VeryBigObject, а может и не понадобится, зависит от условий и событий происходящих во время выполнения программы. Мы знаем о том, что создание и инициализация объекта VeryBigObject займет большое время, а вероятность того, что он понадобится не очень велика, поэтому вместо инициализации экземпляр VeryBigObject во время инициализации объекта класса A мы бы хотели инициализировать объект VeryBigObject непосредственно перед его использованием, вот один из способов добиться такого поведения:
class A(object):
def __init__(self):
self.__lazy_attr = None
@property
def lazy_attr(self):
if self.__lazy_attr is None:
self.__lazy_attr = VeryBigObject()
return self.__lazy_attr
def process(self):
try:
...
except SomeRareError, error:
self.__lazy_attr.process(error)
except AnotherRareError, error:
self.__lazy_attr.process(error)
Декоратор.
Сегодня мне наконец-то надоело писать один и тот-же код, а именно установку и проверку значений приватных атрибутов. Немного подумав выдумал вот такой декоратор, делающий за меня надоевшие телодвижения:
def lazy(func):
@property
def wrapper(self):
attr_name = '__%s' % func.__name__
try:
value = getattr(self, attr_name)
except AttributeError:
value = func(self)
setattr(self, attr_name, value)
return value
return wrapper
И сразу же пример того, как выглядел бы наш класс A, если бы мы использовали декоратор lazy:
class A(object):
@lazy
def lazy_attr(self):
return VeryBigObject()
....
Декоратор работает очень просто, он оборачивает указанный метод, в нашем случае это lazy_attr .При этом обернутый метод становится свойством (property) объекта. Далее, при первом обращении к свойству, декоратор устанавливает приватный атрибут вида “__имя_свойства”, у нас это будет атрибут self.__lazy_attr. Значением которого является результат вызова обернутого метода и возвращает это значение. Обернутый нами метод lazy_attr вернет экземпляр VeryBigObject. При следующих обращениях декоратор просто берет из установленного им атрибута значение и возвращает его запросившей стороне.
Немного запутанно, но, я надеюсь, глядя на код вы разберетесь. :)
Метки: decorators
Июнь 11, 2008 в 2:26 пп
[...] programmizm описывает ленивую инициализацию. А также пример того, как можно использовать [...]
Сентябрь 24, 2008 в 2:24 пп
[...] этом побочных эффектов и значительных неудобств.lazy initialization, python Ленивая инициализация и для чего она нужна, [...]