Ответ
Lazy loading (ленивая загрузка) — это паттерн, при котором инициализация объекта откладывается до момента первого обращения к нему. Это оптимизирует производительность и экономит память, особенно при работе с ресурсоемкими объектами.
В Python его можно реализовать несколькими способами:
-
С помощью декоратора
@propertyСамый распространенный подход. Значение вычисляется только при первом доступе к свойству и затем кэшируется в приватном атрибуте объекта.class DataProcessor: def __init__(self, source_file): self._source_file = source_file self._heavy_data = None @property def heavy_data(self): if self._heavy_data is None: print(f"Loading data from {self._source_file}...") # Здесь происходит ресурсоемкая операция self._heavy_data = [i for i in range(10**6)] return self._heavy_data processor = DataProcessor("my_file.csv") # 'heavy_data' еще не загружены print(len(processor.heavy_data)) # Произойдет загрузка print(len(processor.heavy_data)) # Используется кэшированное значение -
Через магический метод
__getattr__Этот метод перехватывает обращения к несуществующим атрибутам, что позволяет инициализировать и вернуть нужный объект "на лету".class LazyLoader: def __init__(self, data_loader_func): self._data_loader_func = data_loader_func self._loaded_object = None def __getattr__(self, name): if self._loaded_object is None: print("Initializing object...") self._loaded_object = self._data_loader_func() return getattr(self._loaded_object, name) # Пример: ленивая загрузка объекта list lazy_list = LazyLoader(lambda: [1, 2, 3]) lazy_list.append(4) # Объект будет создан здесь print(lazy_list._loaded_object) # [1, 2, 3, 4] -
Использование генераторов Генераторы по своей природе ленивы — они вычисляют следующее значение в последовательности только по запросу (например, в цикле
forили черезnext()), не храня все значения в памяти.# Эта функция не создает список сразу def lazy_range(n): print("Generator started") i = 0 while i < n: yield i i += 1 # Значения вычисляются по одному при итерации for num in lazy_range(5): print(num) -
Готовые решения в библиотеках Многие фреймворки предоставляют готовые реализации. Например,
cached_propertyв Django и Werkzeug (библиотека Flask) работает аналогично примеру с декоратором, но является более надежным и протестированным решением.