0

I am trying to creating a python dataclass where fields can have formatted values. If I have the following

@dataclass(kw_only=True)
class childtestProduct(testProduct):

  t1:float 
  t2:str

how can I have for example t1 be like 99.90€ and t2 be like 10/8/2002 ?

9
  • What are you trying to achieve? Say t1 is 99.9 (float), when do you want it to become "99.90€" (string)? Commented Aug 10, 2022 at 19:14
  • what would be input of the datalclass? Commented Aug 10, 2022 at 19:18
  • 1
    so for ex would a user would pass in 99.9€ or a float 7.893217854? also would a string be pass in to date value so ilke 02/08/10 for example? Commented Aug 10, 2022 at 19:19
  • 1
    a float of 7.8909080 and for t2 maybe the value is initialy 1/10/22 and become 1/10/2022 Commented Aug 10, 2022 at 19:20
  • 1
    You could probably do this because Python will let you do almost anything. However, for your case, you might want to consider a regular class and use the @property decorator so that setting the instance attributes programmatically defines your attributes the way you want. With properties, you can even store a true value and return a formatted value with the attribute getter. Commented Aug 10, 2022 at 19:24

1 Answer 1

5

You could use an approach with @property decorator, as mentioned, and turn all dataclass fields into field properties:

from dataclasses import dataclass
from datetime import datetime, date


@dataclass(kw_only=True)
class ChildTestProduct:
    t1: float
    t2: datetime | str

    @property
    def t1(self) -> str:
        return f'{self._t1:.2f}€'

    @t1.setter
    def t1(self, value: float):
        self._t1 = value

    @property
    def t2(self) -> str:
        return self._t2.strftime('%m/%d/%Y')

    @t2.setter
    def t2(self, value: datetime | str):
        if isinstance(value, str):
            self._t2 = datetime.strptime(value, '%m/%d/%y').date()
        else:
            self._t2 = value


p = ChildTestProduct(t1=99.9, t2='10/8/22')
print(p)  # ChildTestProduct(t1='99.90€', t2='10/08/2022')

assert isinstance(p._t1, float)
assert isinstance(p._t2, date)
Sign up to request clarification or add additional context in comments.

2 Comments

Maybe this is irrelevant in this case, but apparently implementing custom getters/setters with the same name as a field causes a bug that when you don't pass a value, it won't complain and set the value to the property object, see stackoverflow.com/questions/69845745/…
@fsimonjetz Yes, this is entirely accurate, if in the above example you would try to create an object like ChildTestProduct(), the getters/setters would fail because dataclasses would pass in the @property object as the default value. The most straightforward resolution I think would be to use a metaclass or similar solution such as one I added in this gist, that will correctly set the __post_init__() so that default values are then passed in as expected.

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.