Python attrs 类属性缓存延迟加载



我有看起来像这样的类:

@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() 能够通过遍历所有 attrs 并仅在实际调用序列化而不是在__init__上初始化 magic 属性来序列化FileObject

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

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

b) 让魔术属性仅在我实际调用它时实例化 ImageMagic 对象。

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

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


一般的不干净解决方案是有一个带有 getter 的@property,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 错误跟踪器上都经常出现。问题在于,这是一个本质上复杂的主题,这就是为什么在某些时候我们决定将其排除在范围之外,除了简单的案例(即直接的判决/astuple),并让社区提出专门的库。

事实上,您可以在attrs wiki中找到一堆用于[sd]erialization的库,但我不知道其中是否有任何库支持您的有效但前卫的用例。

也就是说,如果两者都不能满足您的需求,您的用例完全可以使用 attrs 的扩展机制和元数据来实现。我不确定你是否可以屈服于你的意愿,但在最坏的情况下,你可以复制/粘贴它并添加你自己的逻辑。功能非常简单。

最新更新