1

バックグラウンド

データクラスを使用して、複雑なテスト出力を表すために使用するネストされたデータ構造を作成しています。

以前は、複数の最上位データクラスを作成してから構成を使用して階層を作成していました。

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))

問題

トップレベルを下位レベルのクラスで汚染するのではなく、自己完結型の方法でクラスを定義する方法があるかどうか疑問に思っていました。上記のように、Pointdataclass の定義には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の出力redとデフォルト設定が正しく行われます10.0

質問

これはネストされたデータクラスを実装する正しい方法ですか?

(つまり、今はうまくいっているが、将来壊れる可能性が高いということですか? ...それとも単に醜いだけで、あなたのやり方に合わない? ...それとも単に悪いことなのか?)

...確かに、膨大な数のトップレベルの「ミニ」データクラスを一緒に構成するよりも、はるかにクリーンで、理解とサポートが100万倍簡単です。

...また、marshmellow を使用したり、json スキーマをクラス構造モデルにジェリーリギングしたりするよりもはるかに簡単です。

...それもとてもシンプルです (私はそれが好きです)

4

1 に答える 1