до сих пор помню что когда ради интереса попробовал написать [объектноориентированный] HellowWorld в среде Visual Basic (а было это ещё лет 7~10 назад) -- то заметил что конструкторы декларированных в коде объектов -- не начнут создавать эти объекты, пока к этому объекту не будет никакого обращения!
(ну тоесть -- зачем зря создавать объекты , пока ими никто не начнёт пользоваться(?).. а вдруг часть объектов так и останеться непользованной!)
...вот подумать.. .... .... Basic -- этож какойто ГОВНОязык... :-) а получается ведь что там есть элементы ленивости x_X [ну по крайней мере в интерпритации Microsoft Visual Basic :-) :-) ] ...
поэтому... вот что я думаю про ленивость инициализаций в Python:
механизм который поможет её создать -- можно описать следущим образом:
# require Python2 or Python3
#-*- coding: UTF-8 *-*
import threading
class SimpleLazyProxy:
'''ленивая инициализация объекта
безопасная для многонитевого использования'''
def __init__(self, factory):
self.__lock = threading.RLock()
self.__obj = None
self.__factory = factory
def __call__(self):
'''функция для доступа к настоящему объекту
если объект не создан, то он создаcтся'''
# пробуем получить "быстрый" доступ к объекту:
obj = self.__obj
if obj is not None:
# получилось!
return obj
else:
# объект возможно ещё не создан
with self.__lock:
# получаем доступ к объекту в эксклюзивном режиме:
obj = self.__obj
if obj is not None:
# оказалось объект уже создан.
# не будем повторно его создавать
return obj
else:
# объект действительно ещё не создан.
# создадим же его!
obj = self.__factory()
self.__obj = obj
return obj
__getattr__ = lambda self, name: \
getattr(self(), name)
def lazy(proxy_cls=SimpleLazyProxy):
'''декоратор превращающий класс, в класс с ленивой инициализацией
средствами Proxy-класса'''
class ClassDecorator:
def __init__(self, cls):
# инициализация декоратора,
# но не декорируемого класса и не Proxy-класса
self.cls = cls
def __call__(self, *args, **kwargs):
# запрос инициализации Proxy-класса
# передадим Proxy-классу нужные параметры
# для инициализации декорируемого класса
return proxy_cls(lambda: self.cls(*args, **kwargs))
return ClassDecorator
# простая проверка:
def test_0():
print('\t\t\t*** Начало теста ***')
import time
@lazy() # экземпляры этого класса будут с ленивой инициализацией
class TestType:
def __init__(self, name):
print('%s: Создаётся...' % name)
# искусственно увеличим время создания объекта,
# для нагнетения конкуренции нитей
time.sleep(3)
self.name = name
print('%s: Создался!' % name)
def test(self):
print('%s: Проверка' % self.name)
# один такой экземпляр будет взаимодействовать с несколькими нитями
test_obj = TestType('Межнитевый тестовый объект')
target_event = threading.Event()
def threads_target():
# функция которую будут выполнять нити:
# ждём наступления специального события
target_event.wait()
# как только это событие наступит --
# все 10 нитей одновременно обратятся к тестовому объекту
# и в этот момент он инициализируется, в одной из нитей
test_obj.test()
# создадим этих 10 нитей, с вышеописанным алгоритмом threads_target()
threads = []
for thread in range(10):
thread = threading.Thread(target=threads_target)
thread.start()
threads.append(thread)
print('До этого момента обращений к объекту не было')
# подождём немного времени...
time.sleep(3)
# ...и одновременно запустим test_obj.test() во всех нитях
print('Активируем событие для использования тестового объекта!')
target_event.set()
# завершение
for thread in threads:
thread.join()
print('\t\t\t*** Конец теста ***')
совсем вроде бы не геморойно :-D :-D
хотя..... при этом получаем разумеется и определённые негативы :-)..
...такие как -- все экземпляры ленивых классов -- на самом деле будут экземплярами Proxy-классов... а значит с ними нельзя будт так свободно работать как с обыкновеннымми экземплярами оригинального класса! (хотя конешно никто не запретит в любое время извлеч из Proxy-экземпляра -- настоящщий оригинальный экземпляр! :)) ну а для некоторых типов объектов -- даже и интерфейс Proxy-класса вполне будет хватать :-)
вобщем, думаю... хотябы кое-где -- это должно иметь место жить :-) :-)