强大的序列化支持NamedTuple&@dataclass数据类型。
pywise的Python项目详细描述
pywise
包含提供通用实用程序并基于Python3标准库构建的函数。它没有外部依赖关系。在
- ^{{cd4>{cd3>反序列化
archives
:解压缩tar归档文件common
:实用程序schema
:获取一个类似dict
的结构,描述任何可序列化类型的字段和类型(有助于以JSON的形式查看)
这个项目最显著的功能是serialize
和{
开发设置
此项目使用^{poetry
。在
要安装项目的依赖项,请执行以下操作:
poetry install
每个命令都必须在poetry
-管理的环境中运行。
例如,要打开Python shell,可以执行以下操作:
或者,您可以通过执行poetry shell
激活环境并直接调用Python程序。在
测试
要运行测试,请执行:
poetry run pytest -v
要对所有支持的环境运行测试,请使用^{
poetry run tox -p
注意:要运行tox
,必须有所有必需的Python解释器可用。
我们建议使用^{
开发工具
此项目使用black
进行代码格式化,flake8
用于linting,以及
mypy
用于类型检查。使用以下命令可确保代码质量:
# formats all code in-place
black .
# typechecks
mypy --ignore-missing-imports --follow-imports=silent --show-column-numbers --warn-unreachable .
# lints code
flake8 --max-line-length=100 --ignore=E501,W293,E303,W291,W503,E203,E731,E231,E721,E722,E741 .
通过示例记录
嵌套@dataclass和NamedTuple
假设您有一个要在JSON中写入和从JSON写入的地址簿。
我们将为AddressBook
定义数据类型:
fromtypingimportOptional,Union,SequencefromdataclassesimportdataclassfromenumimportEnum,auto@dataclass(frozen=True)className:first:strlast:strmiddle:Optional[str]=NoneclassPhoneNumber(NamedTuple):area_code:intnumber:intextension:Optional[int]=None@dataclass(frozen=True)classEmailAddress:name:strdomain:strclassContactType(Enum):personal,professional=auto(),auto()classEmergency(NamedTuple):full_name:strcontact:Union[PhoneNumber,EmailAddress]@dataclass(frozen=True)classEntry:name:Namenumber:PhoneNumberemail:EmailAddresscontact_type:ContactTypeemergency_contact:Emergency@dataclass(frozen=True)classAddressBook:entries:Sequence[Entry]
为了进行说明,让我们考虑以下实例化的AddressBook
:
ab=AddressBook([Entry(Name('Malcolm','Greaves',middle='W'),PhoneNumber(510,3452113),EmailAddress('malcolm','world.com'),contact_type=ContactType.professional,emergency_contact=Emergency("Superman",PhoneNumber(262,1249865,extension=1))),])
我们可以使用serialize
将AddressBook
数据类型转换为JSON格式的字符串:
fromcore_utils.serializationimportserializeimportjsons=serialize(ab)j=json.dumps(s,indent=2)print(j)
我们可以使用deserialize
轻松地将JSON字符串转换回新的实例化AddressBook
:
fromcore_utils.serializationimportdeserialized=json.loads(j)new_ab=deserialize(AddressBook,d)print(ab==new_ab)# NOTE: The @dataclass(frozen=True) is only needed to make this equality work.# Any @dataclass decorated type is serializable.
注意,deserialize
函数需要将数据反序列化为的类型。应得的
类型匹配是structural:只要数据类型的结构(字段名和
关联类型)与提供的数据兼容。在
自定义序列化
如果希望将serialize
和deserialize
与来自第三方库(例如numpy
数组)或自定义的class
的数据类型一起使用,那么可以提供NamedTuple
的serialize
和{CustomFormat
。在
CustomFormat
是将精确类型与自定义序列化函数相关联的映射。当提供给serialize
时,映射中的值接受确切类型的实例并生成可序列化表示。在deserialize
函数中,它们将这种序列化表示转换为该类型的真实实例。在
为了说明它们的用法,我们将介绍CustomFormat
dict
,它允许我们序列化numpy
多维数组:
importnumpyasnpfromcore_utils.serializationimport*custom_serialization:CustomFormat={np.ndarray:lambdaarr:arr.tolist()}custom_deserialization:CustomFormat={np.ndarray:lambdalst:np.array(lst)}
现在,我们可以为函数提供custom_{serialization,deserialization}
。我们将使用它们对一个浮点数的四维数组执行“往返”序列化,并从JSON格式的str
执行序列化:
importjsonv_original=np.random.random((1,2,3,4))s=serialize(v_original,custom=custom_serialization)j=json.dumps(s)d=json.loads(j)v_deser=deserialize(np.ndarray,d,custom=custom_deserialization)print((v_original==v_deser).all())
需要注意的是,当提供CustomFormat
时,序列化函数优先于默认行为(除了Any
,因为always被认为是传递)。此外,类型必须与映射中的键精确匹配。因此,如果使用泛型类型,则必须为每个不同的类型参数化提供单独的键值实体。在
- 项目
标签: