【发布时间】:2020-06-18 09:37:44
【问题描述】:
请参阅下面的示例,使用 python 3.7,我无法找到正确注释的方法。注释错误以 cmets 显示,由 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()
【问题讨论】:
-
对于“Child.useIt”方法,解决方法是在使用 self.provider.p 之前“断言 isinstance(self.provider, self.providerType)”。但这在 Parent.provider 中不起作用,因为它还不知道最终的 providerType 类型。
-
这里有几个不清楚的地方。您将关键字参数传递给
providerType,但您没有将其定义为接受任何参数。providerKwargs是一种方法,但您没有调用它(您将其视为dict本身)。 -
谢谢@chepner。在 Parent.provider 属性中实例化提供程序时,Parent 使用 providerKwargs。
-
谁用没关系,因为你用错了。如果它是一个方法,你必须调用它:
return self.providerType(**self.providerKwargs())。并且您仍然需要将providerType的签名更改为accept 关键字参数。 -
@chepner providerKwargs 是一个属性...
标签: python python-3.x mypy type-annotation