You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中创建延迟初始化(代理)包装器?

实现延迟初始化的对象包装器

我们需要创建一个包装器,将初始化成本极高的类A的实例化操作,延迟到第一次访问其任意属性(包括直接访问__dict__)时才执行,以此达到func1传入代理后立即执行、func2访问属性时才触发初始化的效果。

修正原代码问题

首先修正原代码中的两处错误:

  • 类A的__init__方法缺少self参数
  • func2中应访问实例的foo属性,而非类的foo属性

延迟初始化包装器实现

以下是具体实现代码:

import time

class A:
    def __init__(self):
        time.sleep(42)
        self.foo = 1

def func1(obj: A):
    pass

def func2(obj: A):
    print(obj.foo)

def wrapper(cls):
    class LazyProxy:
        def __init__(self):
            self._cls = cls
            self._instance = None
        
        def __getattribute__(self, name):
            # 跳过代理自身内部属性,避免无限递归
            if name in ('_cls', '_instance', '__class__'):
                return super().__getattribute__(name)
            
            # 首次访问非内部属性时,初始化真实实例
            if self._instance is None:
                self._instance = self._cls()
            
            # 将属性访问转发给真实实例
            return getattr(self._instance, name)
    
    return LazyProxy()

代码说明

  • LazyProxy作为代理类,持有目标类cls和未初始化的实例引用_instance
  • __getattribute__拦截所有属性访问:
    • 对代理自身的内部属性直接返回,避免递归调用
    • 访问其他属性时,先检查是否已初始化真实实例,未初始化则执行实例化
    • 最后将属性访问转发给真实实例
  • 该实现覆盖常规属性访问(如proxy.foo)和直接访问__dict__(如proxy.__dict__['foo'])的场景,都会触发初始化

测试验证

运行以下代码验证效果:

proxy = wrapper(A)
func1(proxy)  # 立即执行,不会触发A的初始化
func2(proxy)  # 触发A的初始化,等待42秒后打印1

扩展支持特殊方法

如果目标类A包含特殊方法(如__call__、__len__),可在LazyProxy中添加对应方法,确保触发初始化后再转发调用。例如支持__call__的示例:

def __call__(self, *args, **kwargs):
    if self._instance is None:
        self._instance = self._cls()
    return self._instance(*args, **kwargs)

内容的提问来源于stack exchange,提问作者y.selivonchyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:58:14