objtyping 带类型定义的对象转换器
由来
Python不是强类型语言,开发人员没有给数据定义类型的习惯。这样尽管灵便,但解决简单业务逻辑的时候却不够不便——不足类型查看可能导致很难发现错误,在IDE里编码时也没有代码提醒。所以开发了这个小工具来解决它。
根本用法
首先定义业务类,并通过类变量定义每个字段的类型。
from typing import Listclass Person: name: str age: intclass Company: name: str revenue: float employees: List[Person]
之所以抉择类变量来定义,是因为它最简洁和直观。相比之下,如果在__init__办法中初始化实例变量,是没有方法获取类型定义(type_hint)的;如果用@property注解或者getter,setter办法的话,显然就更简单了。它们都不如间接定义类变量简略柔美。不过应用类变量也有毛病:就是它在这里被当成元数据来应用了,如果真的须要定义类级别共享的变量,无奈辨别。这个问题能够在前面通过开发自定义注解来解决。
下一步就能够把合乎这个类定义构造的dict-list嵌套数据,转化为该类实例对象了:
from objtyping import objtypingcompany1 = objtyping.from_dict_list({ 'name': 'Apple', 'revenue': 18.5, 'employees': [{ 'name': 'Tom', 'age': 20 }, { 'name': 'Jerry', 'age': 31 }]}, Company)
此时的company1就是残缺的Company对象了, 能够间接应用company1.name, company1.employees[0].name 等模式拜访外面的属性。
当然也能够把业务对象再转回dict-list嵌套的模式
from objtyping import objtypingdict_list = objtyping.to_dict_list(company1)
此时的dict_list对象,就是一大堆dict和list层级嵌套的原始类型数据
应用场景
初始化对象
Python没有js那么不便的初始化对象形式,但有这个工具就能够这样写(就是后面根底应用的汇总):
from typing import Listfrom objtyping import objtypingclass Person: name: str age: intclass Company: name: str revenue: float employees: List[Person] def __str__(self): # 其实个别可能都是这样简略用一下的 return "'{}' has {} employees: {}".format(self.name, len(self.employees), ' and '.join(map(lambda emp: emp.name, self.employees)))if __name__ == '__main__': company1 = objtyping.from_dict_list({ 'name': 'Apple', 'revenue': 18.5, 'employees': [{ 'name': 'Tom', 'age': 20 }, { 'name': 'Jerry', 'age': 31 }] }, Company) print(company1)
输入后果:
'Apple' has 2 employees: Tom and Jerry
序列化/反序列化
Python的常见的序列化需要,包含json和yaml数据格式,它们都有绝对欠缺的解决库。但同样是不强调类型的缘故,它们解决的对象都是原始的dict-list格局。正好能够借助这个工具实现进一步转化。
json
示例
import jsonimport sysfrom typing import Listfrom objtyping import objtypingclass X: x: int y: strclass A: q: str a: str b: int c: List[X]if __name__ == '__main__': print("\r\n-----json-------") json_obj = json.loads('{"q":9, "a":"Mark", "b":3, "c":[{"x":15, "y":"male"},{"x":9, "y":"female", "z":13}]}') typed_obj = objtyping.from_dict_list(json_obj, A) d_l_obj = objtyping.to_dict_list(typed_obj) print(json.dumps(d_l_obj)) sys.exit()
输入后果
-----json-------{"q": "9", "a": "Mark", "b": 3, "c": [{"x": 15, "y": "male"}, {"x": 9, "y": "female", "z": 13}]}
这里须要留神的是:原本属性"q",在最后的json构造中,是个数字,但因为类变量定义中是字符串,转换成业务对象当前,它的类型就是字符串了——objtyping工具,会试图依照类定义,在根底类型之间强制转换。
yaml
示例
import sysfrom ruamel.yaml import YAMLfrom typing import Listfrom objtyping import objtypingclass X: x: int y: strclass A: q: str a: str b: int c: List[X]if __name__ == '__main__': print("\r\n-----yaml-------") yaml = YAML() yaml_obj = yaml.load(''' q: 9 a: Mark b: 3 c: - x: 15 y: male - x: 9 y: female z: 13 ''') typed_obj = objtyping.from_dict_list(yaml_obj, A) d_l_obj = objtyping.to_dict_list(typed_obj) yaml.dump(d_l_obj, sys.stdout) sys.exit()
输入后果
-----yaml-------q: '9'a: Markb: 3c:- x: 15 y: male- x: 9 y: female z: 13
这里的属性"q"同样被强转了类型。
我的项目地址:>https://github.com/songofhawk...