具有可选参数但非可选字段类型的 Python 冻结数据类

Python frozen dataclass with an optional parameter but non-optional field type

提问人:Pastafarianist 提问时间:10/20/2023 更新时间:10/21/2023 访问量:51

问:

我有一个这样的数据类:

@dataclasses.dataclass(frozen=True)
class MyClass:
    my_field: str
    other_field: str

我有一个复杂的函数来计算默认值,这取决于:my_fieldother_field

def get_default_value_for_my_field(other_field: str) -> str:
    ...  # lots of code

有没有办法:

  1. 如果在初始化时没有传递 for 值,则从其结果调用并初始化,否则从传递的值初始化;get_default_value_for_my_field(other_field)my_fieldmy_fieldmy_field
  2. 保持冷冻;MyClass
  3. 说服有类型而不是pytypeMyClass.my_fieldstrstr | None;
  4. 说服有一个参数pytypeMyClass.__init__()my_field: str | None = None

使用数据类,还是我最好切换到普通类?

蟒蛇 python-dataclasses

评论


答:

0赞 Lucas M. Uriarte 10/21/2023 #1

我不认为所有这些条件都可以使用 daclasses。我曾经遇到过同样的问题,并找到了一个实际上可以很容易地解决上述所有问题的软件包。该包是 call attrs,如果您使用 dataclasses,您可以看到它执行相同的操作,但添加了一些非常酷的功能,而不会干扰类或类似于 pydantic 所做的。 它的工作方式与数据类相同,您可能需要更改很少的代码才能从 dataclass 移动到 attrs,但它确实添加了一个新的依赖项。

from attrs import define

def get_default_value_for_my_field(other_field: str) -> str:
    ...  # lots of code


@define(frozen=True)
class MyClass:
    other_field: str
    my_field: str 

    def __init__(self, other_field: str, my_field: str|None):
        if not my_field:
            my_field = get_default_value_for_my_field(other_field)
        self.__attrs_init__(other_field=other_field, my_field=my_field)
1赞 Brian61354270 10/21/2023 #2

将“命名构造函数”类方法添加到您的数据类中:

@dataclasses.dataclass(frozen=True)
class MyClass:
    my_field: str
    other_field: str

    @classmethod
    def from_other(cls, other_field: str) -> MyClass:
        my_field = default_for_my_field(other_field)
        return cls(my_field, other_field)

然后,您可以创建实例作为MyClass

MyClass("my field", "other field")

MyClass.from_other("other field")

使用这种方法,将保持为“哑”纯旧数据类。特殊的默认值逻辑仅在用户请求时启动(通过使用“命名构造函数”)。MyClass

评论

0赞 Pastafarianist 10/23/2023
是的,这是我目前的方法。我想我应该在我的条件列表中包括“避免创建额外的构造函数,而只是使用 ”。__init__()