python - Python attrs/cattrs 使用冻结的 attrs 类作为字典键序列化字典
问题描述
我想构造和解构一个attrs
对象,其中包括dict
使用简单冻结属性作为 dict 键的字段。这对于在运行时创建的对象非常有效,但是 freeze 属性无法使使用 cattrs 的 un/structuring 变得容易。
这是问题的一个简单示例:
import attr, cattr
# Simple attr that contains only a single primitive data type.
@attr.s(frozen=True)
class AbstractID:
_id: Optional[int] = attr.ib()
def __str__(self) -> str:
if self._id is not None:
return f"A{self._id}"
else:
return "—"
@attr.s(auto_attribs=True)
class Database:
storage: dict[AbstractID, str] = {}
# Attempt to unstructure using cattrs
db = Database()
db.storage[AbstractID(1)] = "some data"
cattr.unstructure(db)
>>> TypeError: unhashable type: 'dict'
在导入/导出过程之外,是否有某种方法可以在不使用 int 或 str 作为 dict 键的情况下序列化数据?我看到 cattrs 提供了自定义序列化过程的钩子,但是我不知道如何在非结构化时将 AbstractID 减少为 int,或者如何将其结构化回 AbstractID。
这可以做到吗?
解决方案
默认方法失败,因为它试图生成:
{"storage": {{"_id": 1}: "some_data"}
并且 Python dicts 不支持其他 dicts 作为键。
由于我们将自定义行为,我们将使用一个单独的转换器实例。我还将使用新的 attrs API,因为它们更干净。这是您想要执行的操作:
from typing import Optional
from attr import define, frozen, Factory
from cattr import GenConverter
# Simple attr that contains only a single primitive data type.
@frozen
class AbstractID:
_id: Optional[int]
def __str__(self) -> str:
if self._id is not None:
return f"A{self._id}"
else:
return "—"
@define
class Database:
storage: dict[AbstractID, str] = Factory(dict)
# Attempt to unstructure using cattrs
db = Database()
db.storage[AbstractID(1)] = "some data"
c = GenConverter()
c.register_unstructure_hook(AbstractID, lambda aid: aid._id)
c.register_structure_hook(AbstractID, lambda v, _: AbstractID(v))
print(c.unstructure(db)) # {'storage': {1: 'some data'}}
print(c.structure(c.unstructure(db), Database)) # Database(storage={AbstractID(_id=1): 'some data'})
cattrs
使这些东西变得容易。
推荐阅读
- openedge - 在填写字段中添加 x 分钟的代码
- html - 为非滚动创建固定位置会弄乱页面上的 div 位置
- oracle - 如何将两行的值合并到同一行的单行中?
- javascript - 切片发生在代码中,但不会在 UI 中更新
- scala - NoSuchMethodException:运行 pyspark 代码 zepplin 时的 scala.tools.nsc.interpreter.ILoop.scala
- c++ - 光线追踪器阴影问题
- keyboard - ahk 在按住键盘上的键的同时单击鼠标按钮
- oracle - 将 Oracle 的 BITAND 与多值参数一起使用
- featuretools - 有没有办法获得实体集中分类变量的每个级别的百分比?
- amazon-web-services - 在 AWS C9 上使用 Storybook 服务器?