在将数据类参数分配为实例属性之前使用函数对其进行处理

问题描述 投票:0回答:3

我正在使用一个数据类,并通过将 json 字典传递给其构造函数来构造该数据类的实例。该字典的某些字段通过字符串表示日期(但这不是这里的问题)。 在将这些字段存储为数据类属性之前,有没有办法捕获并处理这些字段(在本例中:将它们转换为 python 日期时间对象)?

更清楚地说: 如果我在经典课程中工作,我会这样做:

class A:
    def __init__(self, dt: str):
        self.dt = datetime.strptime(dt, my_date_format)

现在,我应该如何修改下面的代码,使其行为与上面的代码相同?

@dataclass
class A:
    dt: str = ""

我的第一个希望是使用

dataclasses.field
,但我在文档中找不到任何可以实现我想要的功能。

我想避免的 2 个解决方案:

  • 使用
    __post_init__
    操作:Python 编码教会我 1 行解决方案通常存在......
  • 在用它构造数据类实例之前改变我的字典。所有机制都应保留在类定义(封装)内。
python python-dataclasses
3个回答
2
投票

我会保持

__init__
“哑”:它需要一个
datetime
对象并用它设置属性。

添加一个 class 方法来预处理字符串,以便在创建新实例之前首先获取

datetime
对象。

@dataclass
class A:
    dt: datetime

    @classmethod
    def from_string(cls, dt):
        return cls(datetime.strptime(dt, my_date_format))

1
投票

如果您同意使用第三方库来简化数据类实例的创建,我建议您查看

dataclass-wizard
来完成此任务。

简单的例子:

from dataclasses import dataclass
from datetime import datetime

from dataclass_wizard import JSONWizard


@dataclass
class A(JSONWizard):
    dt: datetime


a = A.from_json('{"dt": "2021-01-02T13:10:52"}')

print(repr(a))  # A(dt=datetime.datetime(2021, 1, 2, 13, 10, 52))

也可以轻松设置自定义日期时间模式(可以解析 ISO 格式字符串):

from dataclasses import dataclass

from dataclass_wizard import JSONWizard, DateTimePattern


@dataclass
class A(JSONWizard):
    dt: DateTimePattern['%m/%d/%y %H.%M.%S']


a = A.from_dict({'dt': '1/02/23 02.03.52'})

print(repr(a))  # A(dt=datetime.datetime(2023, 1, 2, 2, 3, 52))

0
投票

您可以使用描述符:

from dataclasses import dataclass
from datetime import datetime


my_date_format = "%Y-%m-%d %H:%M:%S"


class DateTime:
    def __set_name__(self, owner, name):
        self._name = "_" + name

    def __get__(self, obj, type):
        return getattr(obj, self._name)

    def __set__(self, obj, value):
        if isinstance(value, str):
            value = datetime.strptime(value, my_date_format)
        setattr(obj, self._name, value)


@dataclass
class A:
    dt: datetime = DateTime()


a = A("2021-01-01 12:00:00")
print(a.dt.timestamp())

# Re-assign string.
a.dt = "2025-01-01 12:00:00"
print(a.dt.timestamp())

# Re-assign datetime.
a.dt = datetime.now()
print(a.dt.timestamp())

输出:

1609498800.0
1735729200.0
1734192045.705296

文档:https://docs.python.org/3/library/dataclasses.html#descriptor-typed-fields

© www.soinside.com 2019 - 2024. All rights reserved.