在软件开发中,我们经常会遇到一些需要大量资源或时间来初始化的对象。如果这些对象在程序的整个生命周期中只被使用一次或很少使用,那么在程序启动时就立即初始化它们将是一种资源浪费。
懒加载是一种设计模式,它推迟了对象的初始化直到其被实际需要的时候。这种方式可以提高程序的启动速度,减少内存消耗,并在某些情况下提高性能。
定义类和属性:首先,定义需要懒加载的类和属性。
使用@property装饰器:利用Python的@property装饰器来创建一个属性,该属性在第一次被访问时初始化对象。
检查初始化状态:在@property装饰器中,检查对象是否已经被初始化,如果没有,则进行初始化。
示例代码
下面是一个简单的Python类,演示了如何实现懒加载:
class HeavyObject:
def __init__(self):
print("HeavyObject is initialized")
class MyClass:
def __init__(self):
self._HeavyObject = None
@property
def heavy_object(self):
if self._HeavyObject is None:
print("Initializing HeavyObject...")
self._HeavyObject = HeavyObject()
return self._HeavyObject
obj = MyClass()
print("Before accessing heavy_object")
obj.heavy_object # 此时HeavyObject会被初始化
在这个例子中,MyClass有一个名为heavy_object的属性,它在第一次被访问时才会初始化HeavyObject。这种方式确保了HeavyObject只有在真正需要时才被创建。
如果你使用的是Python 3.7或更高版本,可以利用dataclasses模块来简化懒加载的实现:
from dataclasses import dataclass, field
@dataclass
class HeavyObject:
def __post_init__(self):
print("HeavyObject is initialized")
@dataclass
class MyClass:
heavy_object: HeavyObject = field(default=None, init=False)
def __post_init__(self):
self.heavy_object = None
@property
def heavy_object(self):
if self._heavy_object is None:
print("Initializing HeavyObject...")
self._heavy_object = HeavyObject()
return self._heavy_object
这里使用了field(default=None, init=False)来避免在__init__方法中初始化heavy_object,然后通过懒加载的方式在属性访问时进行初始化。
使用场景:当你的程序只在特定条件下需要某个模块时,可以将导入语句放在这些条件内部。
示例:
def use_database():
from myapp import database
database.connect()
使用场景:当你想要在访问不存在的属性时动态加载模块或对象。
class MyModule:
def __getattr__(self, item):
if item == 'module':
import some_module
return some_module
raise AttributeError(f"'MyModule' object has no attribute '{item}'")
my_module = MyModule()
# 当第一次访问module属性时,some_module会被导入
my_module.module.do_something()
class YourClass: # 假设的类名
# ... 类的其他部分 ...
def __getattr__(self, name):
import importlib
module_mapping = {
"ui_automator": ("vehicle_control_tools.auto_element", "UiAutomator2", {"devices": self.cdc_serial}),
"image_handler": ("vehicle_control_tools.image_handle", "ImageHandle", {}),
"log_handler": ("vehicle_control_tools.log_handle", "CDCLogUtil", {"adb": self.adb, "qdb": self.qdb}),
"ocr_tool": ("vehicle_control_tools.ocr.ocr", "OCR", {}),
"mini_screen": ("vehicle_control_tools.Minicap.mini_screen", "MiniScreen", {"adb": self.adb}),
# 其他工具类的映射...
}
if name in module_mapping:
module_path, class_name, kwargs = module_mapping[name]
module = importlib.import_module(module_path)
cls = getattr(module, class_name)
kwargs["logger"] = self.logger
self.logger.info(f"初始化 {class_name}")
return cls(**kwargs)
# SSH特殊处理,避免硬编码密码
if name == "ssh_client":
from vehicle_control_tools.ssh import SSH
ssh_config = self.get_ssh_config() # 假设这个方法从配置文件或环境变量中获取SSH配置
self.logger.info("SSH客户端")
return SSH(**ssh_config)
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
def get_ssh_config(self):
# 实现获取SSH配置的逻辑,例如从配置文件或环境变量中读取
# 返回包含'host', 'username', 'password'等键的字典
pass # 需要根据实际情况实现此方法