Python 继承类型和成员重载的类型注释问题

Python type annotation issues with inheriting types and members overload

请看下面的例子,python 3.7,我找不到正确注释的方法。注释错误显示在注释中,由mypy给出。

正确注释的方法是什么?

非常感谢。

import abc
import typing


class ParentProvider(metaclass=abc.ABCMeta):
    def __init__(self) -> None:
        pass


class ChildProvider(ParentProvider):
    def __init__(self, who: str) -> None:
        ParentProvider.__init__(self)
        self._who: str = who

    @property
    def p(self) -> str:
        return "Hello %s" % self._who


class Parent(metaclass=abc.ABCMeta):
    @property
    @abc.abstractmethod
    def providerType(self) -> typing.Type[ParentProvider]:
        pass

    @property
    @abc.abstractmethod
    def providerKwargs(self) -> typing.Dict[str, typing.Any]:
        pass

    @property
    def provider(self) -> ParentProvider:
        # How to avoid the following error?
        # error: Too many arguments for "ParentProvider"  [call-arg]
        return self.providerType(**self.providerKwargs)

    @abc.abstractmethod
    def useIt(self) -> None:
        pass


class Child(Parent):
    @property
    def providerType(self) -> typing.Type[ParentProvider]:
        # Using Type[ChildProvider] instead Type[ParentProvider]
        # doesn't helps
        return ChildProvider

    @property
    def providerKwargs(self) -> typing.Dict[str, typing.Any]:
        return dict(who='world')

    def useIt(self) -> None:
        # How to avoid the following error?
        # error: "ParentProvider" has no attribute "p"  [attr-defined]
        print(self.provider.p)


if __name__ == "__main__":
    Child().useIt()

I have a "generic class" which implements "generic members"

然后这样标记:

from typing import Generic, TypeVar


_T = TypeVar('_T', bound='ParentProvider')


class Parent(Generic[_T], metaclass=abc.ABCMeta):
    @property
    @abc.abstractmethod
    def providerType(self) -> typing.Type[_T]:
        pass

    @property
    @abc.abstractmethod
    def providerKwargs(self) -> typing.Dict[str, typing.Any]:
        pass

    @property
    def provider(self) -> _T:
        return self.providerType(**self.providerKwargs)

    @abc.abstractmethod
    def useIt(self) -> None:
        pass

现在具体的 Child impl 变为:

class Child(Parent[ChildProvider]):
    @property
    def providerType(self) -> typing.Type[ChildProvider]:
        return ChildProvider

    @property
    def providerKwargs(self) -> typing.Dict[str, typing.Any]:
        return dict(who='world')

    def useIt(self) -> None:
        print(self.provider.p)

How to avoid the following error?

error: Too many arguments for "ParentProvider"  [call-arg]

Parent.__init__ 签名不允许传递任何参数 - 您可以使用

放宽它
class ParentProvider(metaclass=abc.ABCMeta):
    def __init__(self, *args, **kwargs) -> None:
        pass

(或者只是

class ParentProvider(metaclass=abc.ABCMeta):
    def __init__(self, **kwargs) -> None:
        pass

如果您不想允许在提供者构造函数中传递位置参数)。