在Python数据类中,为什么InitVar可以具有默认值但没有default_factory?

Jac*_*era 5 python python-3.7 python-dataclasses

在Python 3.7中,我可以使用默认值创建一个数据类InitVar

from dataclasses import dataclass, InitVar, field

@dataclass
class Foo:
    seed: InitVar[str] = field(default='tomato')
    stored: str = field(init=False)

    def __post_init__(self, seed: str):
        self.stored = f'planted {seed}'

print(Foo())
Run Code Online (Sandbox Code Playgroud)

现在,我尝试创建一个具有可变默认值的类似数据类,而我需要使用它:default_factory

from dataclasses import dataclass, InitVar, field
from typing import List

@dataclass
class Bar:
    seeds: InitVar[List[str]] = field(default_factory=list)
    stored: List[str] = field(init=False)

    def __post_init__(self, seeds: List[str]):
        self.stored = [f'planted {seed}' for seed in seeds]

print(Bar())
Run Code Online (Sandbox Code Playgroud)

但是,这是无效的。Python加注TypeError: field seeds cannot have a default factory

dataclasses.py标准库中的文件没有说明原因:

    # Special restrictions for ClassVar and InitVar.
    if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR):
        if f.default_factory is not MISSING:
            raise TypeError(f'field {f.name} cannot have a '
                            'default factory')
        # Should I check for other field settings? default_factory
        # seems the most serious to check for.  Maybe add others.  For
        # example, how about init=False (or really,
        # init=<not-the-default-init-value>)?  It makes no sense for
        # ClassVar and InitVar to specify init=<anything>.
Run Code Online (Sandbox Code Playgroud)

为什么?这项特殊限制的依据是什么?这有什么意义?

Ray*_*ger 10

理由是提供 adefault_factory几乎总是一个错误。

的目的InitVar是创建一个伪字段,称为“仅初始化字段”。post_init()如果该值不是默认值,则几乎总是会填充该值。模块级 fields() 函数永远不会返回它。主要用例是初始化依赖于一个或多个其他字段的字段值。

考虑到这种意图,提供以下内容几乎总是一个用户错误default_factory

  1. 我们希望看到fields()函数返回的东西。

  2. 如果我们使用post_init()可以直接调用工厂的地方,则完全没有必要。

  3. 不适合对象创建依赖于其他字段值的情况。