Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

I want to be able to override the __repr__ function in my dataclasses to include all class variables from self.dict, not just fields, but still omitting fields with repr=False, including in nested dataclasses.

Simplified version of my code:

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)

What I want (this or something similar):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Foo(foo=0, bar=Bar(...)) but still keep the same formatting when asked print(foo.bar): Bar(bar=0)

What I get with the default repr (the code is functional so things like foo.bar.bar work as intended, I want the repr to display everything omitting fields where repr=False):

Foo(foo=0)

Solutions I’ve tried:

# 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})'

Any help would be appreciated, thanks!

>Solution :

You have to declare the type of bar and disable its initialisation.

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'))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading