如何注释数据类中字段的类型与其 __init__ 的类型不同?

Yoh*_*hei 6 python mypy python-dataclasses

我创建了一个数据类Foo,它接受任何可以转换为的类型int

import dataclasses


@dataclasses.dataclass
class Foo:
    a: int

    def __post_init__(self):
        # Here `self.a` is converted to int, so this class accepts any type that can be converted to int
        self.a = int(self.a)


# mypy error: Argument 1 to "Foo" has incompatible type "str"; expected "int",
foo = Foo("1")
print(foo)
print(foo.a + 2)
Run Code Online (Sandbox Code Playgroud)

输出:

Foo(a=1)
3
Run Code Online (Sandbox Code Playgroud)

但是,mypy 报告以下错误:

error: Argument 1 to "Foo" has incompatible type "str"; expected "int"
Run Code Online (Sandbox Code Playgroud)

Foo.a如果我修复to的类型Union[str, int],mypy 会报告另一个错误:

error: Unsupported operand types for + ("str" and "int")
Run Code Online (Sandbox Code Playgroud)

如何编写字段类型和初始化参数不同的数据类?

use*_*ica 5

您希望将a字段与所采用的a参数解耦__init__。这本质上需要

a: InitVar[Union[SupportsInt, str]]
Run Code Online (Sandbox Code Playgroud)

a: int = field(init=False)
Run Code Online (Sandbox Code Playgroud)

一个用于描述__init__论点,一个用于描述领域。但你不能那样做。InitVar 和字段不能具有相同的名称。

您最好的选择是不使用数据类,但如果您绝对决定这样做,则必须编写自己的__init__

@dataclasses.dataclass
class Foo:
    a: int
    
    def __init__(self, a: typing.Union[typing.SupportsInt, str]):
        self.a = int(a)
Run Code Online (Sandbox Code Playgroud)

  • @Yohei:嗯,`__post_init__`不会运行(除非你自己调用它),你必须手动设置通常为你处理的所有字段,以及处理默认值和默认工厂。 (2认同)