python3: dataclass 个人 tips 合集

dataclass 是 python3 很好用的一个官方库,可以有效地节省各类数据体在 __init__() 中重复类似 self.name = name 的书写。

总(抄)结(袭)了一些好用的自定义方法,让 dataclass 用起来更舒服。

返回所有非 None 元素作为字典

from dataclasses import dataclass, asdict, fields


def factory_filter(data: list) -> dict:
    return dict(duple_item for duple_item in data if duple_item[1] is not None)


@dataclass
class BaseDataClass:
    """基础数据类"""

    def get_data(self) -> dict:
        """返回所有非 None 元素的字典"""
        return asdict(self, dict_factory=factory_filter)

测试:

@dataclass
class Person(BaseDataClass):
    name: str
    age: str
    sex: str = None


peter = Person(name="peter", age=17)
peter.get_data()

输出:

{'name': 'peter', 'age': 17}

工厂方法:自动忽略未定义的传入变量

如果用传入未定义的变量,那么会自动出错,比如:

peter = Person(name="peter", age=17, job='student')
---------------------------------------------------------------------------
TypeError  Traceback (most recent call last)
<ipython-input-4-948a3ccfe901> in <module>
      6 
      7 
----> 8 peter = Person(name="peter", age=17, job='student')

TypeError: __init__() got an unexpected keyword argument 'job'

还是上面的 BaseDataClass, 添加类方法:

    @classmethod
    def create_from_dict(cls, **dict_) -> dataclass:
        """工厂方法,自动忽略非 dataclass 参数"""
        class_fields = {f.name for f in fields(cls)}
        return cls(**{k: v for k, v in dict_.items() if k in class_fields})

再试一次:

peter = Person(name="peter", age=17)
print(Person.create_from_dict(name="peter", age=17, job='student').get_data())

输出:

{'name': 'peter', 'age': 17}