3

Hi I am new to Python.
I have worked with classes before, but not with Dataclasses. In regular classes I can set a attribute of my class by using other attributes. And also using functions to modifiy the attribute when initializing an object of my class.

class Person:
    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = self.to_upper(last_name)
        self.full_name = f"{self.first_name}_{self.last_name}"

    def to_upper(self, some_string):
        return some_string.upper()

p1 = Person("john", "doe")
print(p1.first_name)
print(p1.last_name)
print(p1.full_name)

I was expecting to do this also with dataclasses, as I see dataclasses to be the improved version of regular classes.

from dataclasses import dataclass, field

@dataclass
class Person:
    first_name: str
    last_name: str = field(default_factory=to_upper)
    full_name: str = field(default_factory=get_fullname)

    def to_upper(self, some_string):
        return some_string.upper()

    def get_fullname(self, first_name, last_name):
        return f"{first_name}_{last_name}"

What am I missing here?

Docs for dataclasses https://docs.python.org/3/library/dataclasses.html

1

1 Answer 1

5

As far as I understand in the moment, the __post_init__() method is used for initialise attributes with class methods.

from dataclasses import dataclass, field

@dataclass(init=True)
class Person:
    name: str = "None"
    surname: str = "Why"

    def to_upper(self,some_string):
        return some_string.lower()

    def get_fullname(self, first_name, last_name):
        return f"{first_name}_{last_name}"

    def __post_init__(self):
        self.name: str = self.to_upper(self.name)



test = Person("Bob","Alice")

See https://www.python.org/dev/peps/pep-0557/#id38

@dataclass
class C:
    a: float
    b: float
    c: float = field(init=False)

    def __post_init__(self):
        self.c = self.a + self.b
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thanks for taking your time. Yes, that looks like something I want. I also found the @property decorator. But that seems to be something else. ``` @dataclass class Person: first_name: str last_name: str full_name: str = "None" @property def get_fullname(self, ): return f"{self.first_name}_{self.last_name}" p = Person("john", "doe") print(p.full_name) print(p) ```` Because in that case, I need to call the function to get the manipulated value I am looking for.
Sorry, the code in the comments does not play nicely. But I could use a @Property decorator. But that would not set my value at init. It would be need to be called. Right?
I had the same question, and was looking for validation that __post_init__ is the way to go. Correct link to the doc would be: docs.python.org/3/library/dataclasses.html#post-init-processing It is clearly stated that Among other uses, this allows for initializing field values that depend on one or more other fields

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.