注释抽象 class 的构造函数以使 Mypy 开心的正确方法是什么?

What is the right way of annotating constructor of abstract class to make Mypy happy?

我有一个抽象基础 class BsaeFoo,我的数据 class 继承自 ChildFoo

from abc import ABCMeta
from typing import Dict, Any, TypeVar, Type
from dataclasses import dataclass

Foo = TypeVar("Foo", bound="BaseFoo")


class BaseFoo(metaclass=ABCMeta):
    @classmethod
    def from_dict(cls: Type[Foo], data: Dict[str, Any]) -> Foo:
        init_data = {key: data.get(key, None) for key in cls.__annotations__}
        return cls(**init_data)


@dataclass
class ChildFoo(BaseFoo):
    x: int
    y: int

运行 Mypy 给我

main.py:12: error: Too many arguments for "BaseFoo"
Found 1 error in 1 file (checked 1 source file)

from_dict 将是子数据 classes 的替代构造函数。它根据 cls.__annotations__ 属性读取输入字典,因此它不会在子 classes 中引发。至于 BaseFoo 本身,检查初始化没有意义,因为它是抽象的 class.

如何在不使用 # type: ignore 的情况下使 BaseFoo.from_dict 通过 Mypy?

BaseFoo

中添加__init__的显式定义
class BaseFoo(ABC):
    def __init__(self, **kwargs: Any) -> None:
        raise NotImplementedError

    @classmethod
    def from_dict(cls: type[Foo], data: Dict[str, Any]) -> Foo:
        init_data = {key: data.get(key, None) for key in cls.__annotations__}
        return cls(**init_data)