Python attrs class 属性缓存延迟加载

Python attrs class attribute cached lazy load

我有 类 看起来像这样:

@attr.s
class ImageMagic(object):
    path = attr.ib()

    _img = attr.ib()

    @_img.default
    def _img(self):
        return Image.open(self.path)

@attr.s
class FileObject(object):
    # Standard
    path = attr.ib()

    # When magic-ed
    magic = attr.ib(default=None)

我的目标是让 attrs.asdict() 能够序列化 FileObject,方法是遍历所有属性并仅在实际调用序列化而不是在 __init__.

因为大多数时候我真的不希望 Magic 库检查对象,因为它是一个昂贵的 IO 操作。

目标:
a) 如何连接两者类

b) 拥有 magic 属性只在我实际调用它时实例化 ImageMagic 对象。

c) 仅调用一次,以便以后调用多次时可以重复使用。

有了这个,我更愿意使用 Attrs 库。


一般不干净的解决方案是使用 @property 和 getter,getter 检查私有 _magic 属性是否存在,如果不存在则加载.

然后以某种方式将 属性 注册到 attrs 库,以便它可以进一步序列化。

这是实际解决方案的示例:

@attr.s
class IOExpensiveClass(object):
    path = attr.ib()

    _hash = attr.ib()

    @_hash.default
    def _img(self):
        return IOOPERATION(self.path)


@attr.s
class FileObject(object):
    # Standard
    path = attr.ib()

    _magic = None

    # Missing attrs registration, that I yet don't know how to write
    @property
    def magic(self):
        return self._magic or IOExpensiveClass(self.path)

你退后一步的问题是连载。 Python 的延迟加载方式确实是使用属性,所以你说对了。

序列化(以及更多的反序列化)问题在这里和 attrs 错误跟踪器上不断出现。问题是它本质上是一个复杂的主题,这就是为什么在某些时候我们决定将它排除在范围之外,除了简单的情况(即直接 asdict/astuple)并让社区提出专门的库。

确实有一堆用于 [sd] 序列化的库,您可以在 attrs wiki 中找到,但我不知道它们是否支持您的有效但前卫的用例.

也就是说,如果两者都不能解决您的需求,您的用例完全可以使用 attrs 来实现 extension machinery and metadata. I'm not sure if you can bend asdict to your will, but in the worst case you can just copy/paste it and add your own logic. The function is quite simple