8

I have a below NormalClass that I want to structure as a dataclass. However I was not sure how I can pass the date_str param without __init__ in the dataclass. Any thoughts?

class FieldDateTime():
    def __init__(self, data, d_format='%m/%d/%y %I:%M %p'):
        try:
            self.data = datetime.strptime(data, d_format)
        except ValueError as e:
            raise ValueError('Dateformat incorrect')

    def __call__(self):
        return self.data

class NormalClass:
    def __init__(self, id, date_str):
        self.id: int = id
        self.dt: FieldDateTime = FieldDateTime(date_str)

@dataclass
class DataClassObj:
    id: int
    dt: FieldDateTime(date_str) 

How do I pass the date_str as an argument in the data class representation (DataClassObj) without the init?

Venu Family
  • 83
  • 1
  • 4

2 Answers2

10

Your question has to be more detailed, but I think this is what you're looking for:

from __future__ import annotations

from datetime import datetime
from dataclasses import dataclass, InitVar, field


class FieldDateTime:
    def __init__(self, data, d_format='%m/%d/%y %I:%M %p'):
        try:
            self.data = datetime.strptime(data, d_format)
        except ValueError as e:
            raise ValueError('Dateformat incorrect')

    def __repr__(self):
        return f"{self.__class__.__name__}({self.data})"

    def __call__(self):
        return self.data


@dataclass
class NormalDataClass:
    id: int
    date_str: InitVar[str]
    dt: FieldDateTime = field(init=False)

    def __post_init__(self, date_str):
        self.dt = FieldDateTime(date_str)


print(NormalDataClass(10, '09/04/21 08:11 PM'))

output (given the dataclass-like __repr__ implementation on FieldDateTime to make it look a bit better):

NormalDataClass(id=10, dt=FieldDateTime(2021-09-04 20:11:00))

from doc:

Init-only fields are added as parameters to the generated __init__ method, and are passed to the optional __post_init__ method.

So we can use InitVar for our date_str and pass it to __post_init__ to create our FieldDateTime object.

Arne
  • 17,706
  • 5
  • 83
  • 99
S.B
  • 13,077
  • 10
  • 22
  • 49
2

If i understood you correctly you want to use python dataclasses to achieve default initialization of the class instances fields. This feature is available since Python 3.7 and it implicitly adds __init__ constructor to the class which initializes the class instance with default values you specify.

The code using it would look like below:

from datetime import datetime


class FieldDateTime():
    def __init__(self, data, d_format='%m/%d/%y %I:%M %p'):
        try:
            self.data = datetime.strptime(data, d_format)
        except ValueError as e:
            raise ValueError('Dateformat incorrect')

    def __str__(self):
        return str(self.data)


from dataclasses import dataclass

@dataclass
class NormalDataClass:
    id: int = 0 # default id
    dt: FieldDateTime = FieldDateTime("02/03/20 05:20 AM") # default date

Below code

ndc = NormalDataClass()
print(ndc.id)
print(ndc.dt)

prints:

0
2020-02-03 05:20:00
rok
  • 9,403
  • 17
  • 70
  • 126
  • User wants to be able to pass the variable date_str as an argument. Your solution hard-codes it to a string. – Brian Dec 09 '21 at 18:34