Python嵌套的数据类...有效吗?

问题描述

背景

我正在使用数据类创建嵌套的数据结构,用于表示复杂的测试输出

以前,我是通过创建多个顶级数据类然后使用组合来创建层次结构的:

from dataclasses import dataclass

@dataclass
class Meta:
    color: str 
    size: float

@dataclass
class Point:
    x: float
    y: float
    stuff: Meta

point1 = Point(x=5,y=-5,stuff=Meta(color='blue',size=20))

问题

我想知道是否存在一种以独立方式定义类的方法,而不是用一堆较低级别的类来污染我的顶层。 因此,在上面,Point数据类的定义包含Meta的定义,而不是顶层的定义。

解决方案?

我想知道是否可以将内部(数据类)类与数据类一起使用并使所有功能正常工作。

所以我尝试了这个:

rom dataclasses import dataclass
from typing import get_type_hints


@dataclass
class Point:

    @dataclass
    class Meta:
        color: str 
        size: float

    @dataclass
    class Misc:
        elemA: bool
        elemB: int 

    x: float
    y: float
    Meta: Meta
    misc: Misc


point1 = Point(x=1,y=2,Meta=Point.Meta(color='red',size=5.5),misc=Point.Misc(elemA=True,elemB=-100))

print("This is the point:",point1)
print(point1.x)
print(point1.y)
print(point1.Meta)
print(point1.misc)
print(point1.Meta.color)
print(point1.misc.elemB)

point1.misc.elemB = 99
print(point1)
print(point1.misc.elemB)

这一切似乎都可以正常工作-打印输出都可以正常工作,并且对(子)成员元素的分配也可以正常工作。

您甚至可以支持嵌套元素的认值:

from dataclasses import dataclass


@dataclass
class Point:

    @dataclass
    class Meta:
        color: str = 'red'
        size: float = 10.0

    x: float
    y: float
    Meta: Meta = Meta()


pt2 = Point(x=10,y=20)
print('pt2',pt2)

...正确打印出pt2的red10.0认值

问题

这是实现嵌套数据类的正确方法吗?

(这意味着它现在还算运气,但是将来可能会崩溃吗?...或者它只是丑陋的,而不是您的工作方式吗?...或者这很糟糕?)

...比起组合成千上万亿个顶级“迷你”数据类,它肯定要干净得多,并且易于理解和升级一百万倍。

...比尝试使用marshmellow或将json模式绑定到类结构模型要容易得多。

...这也非常简单(我喜欢)

解决方法

您可以仅使用字符串来注释尚不存在的类:

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float
    stuff: "Meta"

@dataclass
class Meta:
    color: str 
    size: float


point1 = Point(x=5,y=-5,stuff=Meta(color='blue',size=20))

这样,您可以按照最有意义的方式对类定义进行重新排序。像mypy这样的静态类型检查器也遵循这种前向引用方式,因为它们是TUI command的一部分,因此没有任何异域。嵌套类也可以解决该问题,但更难读the initial pep on type annotation