python中类的嵌套_在Python中创建嵌套的数据类对象

这是一个复杂度与dataclasses模块本身的复杂性相匹配的请求:这意味着实现这种“嵌套字段”功能的最佳方法可能是定义一个新的装饰器,类似于@dataclass。

幸运的是,如果一个人不需要__init__方法的签名来反映字段及其默认值,就像通过调用呈现的类一样dataclass,这可以简化得多:一个类装饰器,它将调用原始dataclass 函数并在其上包含一些功能生成的__init__方法可以使用普通的“ ...(*args, **kwargs):”样式函数。

换句话说,所有人需要做的是生成的__init__方法的包装器,它将检查在“kwargs”中传递的参数,检查是否有任何对应于“dataclass字段类型”,如果是,则在调用之前生成嵌套对象原来的__init__。也许这比用Python更难用英语拼出:

来自dataclasses import dataclass,is_dataclassdef nested_dataclass(*args, **kwargs):

def wrapper(cls):

cls = dataclass(cls, **kwargs)

original_init = cls.__init__

def __init__(self, *args, **kwargs):

for name, value in kwargs.items():

field_type = cls.__annotations__.get(name, None)

if is_dataclass(field_type) and isinstance(value, dict):

new_obj = field_type(**value)

kwargs[name] = new_obj

original_init(self, *args, **kwargs)

cls.__init__ = __init__

return cls

return wrapper(args[0]) if args else wrapper

请注意,除了不担心__init__签名之外,这也忽略了传递init=False- 因为无论如何它都没有意义。

(if返回行中的代码负责使用命名参数调用或直接作为装饰器,就像dataclass它本身一样)

并在交互式提示符上:In [85]: @dataclass

...: class A:

...: b: int = 0

...: c: str = ""

...:

In [86]: @dataclass

...: class A:

...: one: int = 0

...: two: str = ""

...:

...:

In [87]: @nested_dataclass

...: class B:

...: three: A

...: four: str

...:

In [88]: @nested_dataclass

...: class C:

...: five: B

...: six: str

...:

...:

In [89]: obj = C(five={"three":{"one": 23, "two":"narf"}, "four": "zort"}, six="fnord")

In [90]: obj.five.three.two

Out[90]: 'narf'

如果你想保留签名,我建议使用dataclasses模块本身的私有帮助函数来创建一个新的__init__。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值