数据类使用 InitVar 默认值来设置实例属性

dataclasses use InitVar default to set instance attribute

提问人:Anthon 提问时间:10/4/2023 最后编辑:Anthon 更新时间:10/4/2023 访问量:71

问:

在数据类中为类型化变量提供默认值时,该属性 对于该变量已设置(实际上,对于缺少默认值的变量,该属性似乎是 在 中主动删除。InitVardataclasses:_process_class()

from dataclasses import dataclass, InitVar, fields

@dataclass
class HasDefault:
    abc: int = 18
    xyz: InitVar[str] = 'oops'

    def __post_init__(self, xyz):
        self.abc += len(xyz)

@dataclass
class NoHasDefault:
    abc: int
    xyz: InitVar[str]

    def __post_init__(self, xyz):
        self.abc += len(xyz)


hd = HasDefault(abc=42, xyz='so long...')
print('field names', [field.name for field in fields(hd)])
print(hd, hd.abc, hd.xyz)
print()
hd2 = HasDefault(abc=42)
print('field names', [field.name for field in fields(hd2)])
print(hd2, hd2.abc, hd2.xyz)
print()
hd3 = HasDefault()
print('field names', [field.name for field in fields(hd3)])
print(hd3, hd3.abc, hd3.xyz)
print()
nhd = NoHasDefault(abc=42, xyz='so long...')
print('field names', [field.name for field in fields(nhd)])
print(nhd, getattr(nhd, 'xyz', 'no attribute xyz'))

这给了:

field names ['abc']
HasDefault(abc=52) 52 oops

field names ['abc']
HasDefault(abc=46) 46 oops

field names ['abc']
HasDefault(abc=22) 22 oops

field names ['abc']
NoHasDefault(abc=52) no attribute xyz

为什么为类型化变量设置属性(当存在默认值时)?我希望永远不会设置此属性,因为它仅用于初始化。这是一个错误吗?xyzInitVar

mypy实际上抱怨这些实例没有属性,所以它的处理方式似乎不同。xyzInitVar

因此,我需要添加一些额外的行才能从 YAML 加载这样的代码,以便以与 YAML 映射中的值相同的方式工作 将用于设置属性,而不是默认值。所以你可以做的(在'ruamel.yaml>0.17.34中)是:dataclass

from dataclasses import dataclass, InitVar
from typing import ClassVar
from ruamel.yaml import YAML

yaml = YAML()

@yaml.register_class
@dataclass
class HasDefault:
    yaml_tag: ClassVar = '!has_default'  # if not set the class name is taken ('!HasDefault')
    abc: int
    xyz: InitVar[str] = 'oops'

    def __post_init__(self, xyz):
        self.abc += len(xyz)

yaml_str = """\
!has_default
abc: 42
xyz: hello world
"""

data = yaml.load(yaml_str)
print(data, data.xyz == 'oops')

给:

HasDefault(abc=53) True

否则就等于data.xyzhello world

默认值 python-dataclasses

评论


答: 暂无答案