创建一个更新的 repr,其中包括在 __post_init__ python 数据类中计算的变量

Create an updated repr that includes variables calculated in __post_init__ python dataclasses

我希望能够在我的数据classes 中覆盖 __repr__ 函数以包含来自自身的所有 class 变量。dict,不仅是字段,而且仍然省略带有 repr=False 的字段,包括嵌套数据 classes.

我的代码的简化版本:

from dataclasses import dataclass, field, fields
import utils

@dataclass
class Bar:
    _data: dict = field(repr=False)
    bar: int = 0

    def __post_init__(self):
        """more nested dataclasses"""

@dataclass
class Foo:
    _data: dict = field(repr=False)
    foo: int = 0

    def __post_init__(self):
        self.bar = Bar(**utils.clean(_data, 'bar'))

foo = Foo(**data)
print(foo)

我想要的(这个或类似的东西):

Foo(foo=0, bar=Bar(...)) 但在询问 print(foo.bar) 时仍保持相同的格式:Bar(bar=0)

我使用默认 repr 得到了什么(代码是功能性的,所以 foo.bar.bar 之类的东西按预期工作,我希望 repr 显示所有省略 repr=False 的字段):

Foo(foo=0)

我尝试过的解决方案:

# works, kinda, but doesn't omit fields where repr=False
def __repr__(self):
    return f'{self.__class__.__qualname__}({self.__dict__!r})'

# modified solution from a similar question on stack overflow, but doesn't return !r formatting
# for every recursion depth when copied to every dataclass and I'm not sure how I would change it
# to format nested dataclasses with '...'
def dict_without_repr_field(self) -> dict:
    dict_to_show = self.__dict__.copy()
    for key in self.__dict__.keys():
        try:
        if not self.__dataclass_fields__[key].repr:
            dict_to_show.pop(key)
        except KeyError:
            pass
    return dict_to_show

def __repr__(self):
    updated_dict = self.dict_without_repr_field()
    return f'{self.__class__.__qualname__}({updated_dict!r})'

任何帮助将不胜感激,谢谢!

您必须声明柱的类型并禁用其初始化。

from dataclasses import field

@dataclass
class Foo:
    _data: dict = field(repr=False)
    foo: int = 0
    bar: Bar = field(init=False) # <-

    def __post_init__(self):
        self.bar = Bar(**utils.clean(_data, 'bar'))