我想创建一个类,当第一次使用对象时,它会在后台惰性地初始化对象,但其行为与初始化的对象完全相同.它应该是线程安全的.例如:

In[1]: l = LazyInitializer(list, (1, 2, 3, 4, 5))
In[2]: l.__len__()
5

我目前的实施是:

class LazyInitializer:

    def __init__(self, initializer, *args, **kwargs):
        self.__initializer = initializer
        self.__args = args
        self.__kwargs = kwargs

        self.__obj = None
        self.__lock = Lock()

    @property
    def _obj(self):
        with self.__lock:
            if self.__obj is None:
                self.__obj = self.__initializer(*self.__args, **self.__kwargs)

        return self.__obj

    def __getattr__(self, item):
        return getattr(self._obj, item)

这适用于常规对象成员(函数和属性类似),但不适用于魔术方法,例如.,

In[2]: l.__len__()  # works
5
In[3]: len(l)  # doesn't work
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-e75269d816bd> in <module>
----> 1 len(l)

TypeError: object of type 'LazyInitializer' has no len()

一个特别的解决方案可以是在LazyInitializer上显式地实现所有可能的魔法方法.然而,难道没有更好的方法吗?

推荐答案

的确

因此,确保以透明方式调用任何可能的magic方法的唯一方法是,如果代理惰性对象拥有所有magic方法.

唯一能起到其他作用的"代理"是"super"本身:但它相当特殊,是语言的一个关键组成部分.通过研究super在C中的实现,您可能会得到一个类似的透明代理(使用C中的一些代码),但这并不能保证.

我曾经放置过一个类似的代理,可以将任何计算卸载到子流程中,这样我就有了一个"透明的future 对象"——它不是漂亮的代码,但我甚至在生产中也使用过它:

https://bitbucket.org/jsbueno/lelo/src/master/

Python相关问答推荐

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

如何使用matplotlib在Python中使用规范化数据和原始t测试值创建组合热图?

如何根据参数推断对象的返回类型?

大小为M的第N位_计数(或人口计数)的公式

关于Python异步编程的问题和使用await/await def关键字

Odoo 16使用NTFS使字段只读

如何保持服务器发送的事件连接活动?

在www.example.com中使用`package_data`包含不包含__init__. py的非Python文件

Python—压缩叶 map html作为邮箱附件并通过sendgrid发送

python sklearn ValueError:使用序列设置数组元素

ModuleNotFoundError:没有模块名为x时try 运行我的代码''

如何在Great Table中处理inf和nans

判断Python操作:如何从字面上得到所有decorator ?

在极点中读取、扫描和接收有什么不同?

计算机找不到已安装的库'

如何从比较函数生成ngroup?

Python OPCUA,modbus通信代码运行3小时后出现RuntimeError

文本溢出了Kivy的视区

如何在PYTHON中向单元测试S Side_Effect发送额外参数?

Pandas 删除只有一种类型的值的行,重复或不重复