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

问题描述 投票:0回答:1

请参阅下面的示例,使用 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()
python mypy python-typing
1个回答
0
投票

我有一个实现“通用成员”的“通用类”

然后将其标记为:

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)

如何避免出现以下错误?

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

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

© www.soinside.com 2019 - 2024. All rights reserved.