关于python:Python-自动将dictlist嵌套数据-转换成-带类型定义的对象

9次阅读

共计 2667 个字符,预计需要花费 7 分钟才能阅读完成。

objtyping 带类型定义的对象转换器

由来

Python 不是强类型语言,开发人员没有给数据定义类型的习惯。这样尽管灵便,但解决简单业务逻辑的时候却不够不便——不足类型查看可能导致很难发现错误,在 IDE 里编码时也没有代码提醒。所以开发了这个小工具来解决它。

根本用法

  • 首先定义业务类,并通过类变量定义每个字段的类型。

    from typing import List
    
    
    class Person:
      name: str
      age: int
    
    
    class Company:
      name: str
      revenue: float
      employees: List[Person]

    之所以抉择类变量来定义,是因为它最简洁和直观。相比之下,如果在__init__办法中初始化实例变量,是没有方法获取类型定义(type_hint)的;如果用 @property 注解或者 getter,setter 办法的话,显然就更简单了。它们都不如间接定义类变量简略柔美。不过应用类变量也有毛病:就是它在这里被当成元数据来应用了,如果真的须要定义类级别共享的变量,无奈辨别。这个问题能够在前面通过开发自定义注解来解决。

  • 下一步就能够把合乎这个类定义构造的 dict-list 嵌套数据,转化为该类实例对象了:

    from objtyping import objtyping
    
    company1 = 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 objtyping
    
    dict_list = objtyping.to_dict_list(company1)

    此时的 dict_list 对象,就是一大堆 dict 和 list 层级嵌套的原始类型数据

应用场景

初始化对象

Python 没有 js 那么不便的初始化对象形式,但有这个工具就能够这样写(就是后面根底应用的汇总):

from typing import List

from objtyping import objtyping


class Person:
    name: str
    age: int


class 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 json
import sys
from typing import List

from objtyping import objtyping


class X:
    x: int
    y: str


class 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 sys
from ruamel.yaml import YAML
from typing import List
from objtyping import objtyping


class X:
    x: int
    y: str


class 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: Mark
b: 3
c:
- x: 15
  y: male
- x: 9
  y: female
  z: 13

这里的属性 ”q” 同样被强转了类型。


我的项目地址:>https://github.com/songofhawk…

正文完
 0