Sun*_*bel 5 abstract-class types python-3.x mypy
我正在编写一个库,在这里我需要一个采用(可能)抽象类型并返回该类型具体子类型的实例的方法:
# script.py
from typing import Type
from abc import ABC, abstractmethod
class AbstractClass(ABC):
@abstractmethod
def abstract_method(self):
pass
T = TypeVar('T', bound=AbstractClass)
def f(c: Type[T]) -> T:
# find concrete implementation of c based on
# environment configuration
...
f(AbstractClass) # doesn't type check
Run Code Online (Sandbox Code Playgroud)
运行mypy script.py收益:
error: Only concrete class can be given where "Type[AbstractClass]" is expected
我不明白此错误消息,并且很难找到有关该错误的任何文档。有什么方法可以注释该函数,以便进行mypy类型检查吗?
附带说明一下,PyCharm的类型检查器是我使用最多的类型检查f,没有错误。
看起来 mypy 确实有点偏向于以这种方式使用抽象基类,尽管正如您所展示的那样,存在有效的用例。
您可以通过使工厂函数成为抽象类上的类方法来解决此问题。如果在风格上您希望将顶级函数用作工厂,那么您可以为类方法创建别名。
from typing import TYPE_CHECKING
from abc import ABC, abstractmethod
class AbstractClass(ABC):
@abstractmethod
def abstract_method(self):
raise NotImplementedError
@classmethod
def make_concrete(cls) -> 'AbstractClass':
"""
find concrete implementation based on environment configuration
"""
return A()
class A(AbstractClass):
def abstract_method(self):
print("a")
# make alias
f = AbstractClass.make_concrete
x = f()
if TYPE_CHECKING:
reveal_type(x) # AbstractClass
Run Code Online (Sandbox Code Playgroud)
请注意,如果没有更多的工作,mypy 无法知道工厂函数创建了哪个具体类,它只会知道它与 兼容AbstractClass,如reveal_type.
或者,如果您愿意放弃由 提供的运行时检查abc.ABC,您可以获得更接近原始设计的东西:
from typing import TYPE_CHECKING
from abc import abstractmethod
class AbstractClass: # do NOT inherit from abc.ABC
@abstractmethod
def abstract_method(self):
raise NotImplementedError
class A(AbstractClass):
def abstract_method(self):
print("a")
class Bad(AbstractClass):
pass
def f() -> AbstractClass:
"""
find concrete implementation based on environment configuration
"""
pass
b = Bad() # mypy displays an error here: Cannot instantiate abstract class 'Bad' with abstract attribute 'abstract_method'
x = f()
if TYPE_CHECKING:
reveal_type(x) # AbstractClass
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为@abstractmethod即使类没有继承自abc.ABC. 但是请注意,如果您使用 python 执行程序,您将不再收到有关实例化Bad类而不实现其抽象方法的错误。
mypy 中存在关于此不当行为(恕我直言)的github 问题。基本上,Type[_T]作为_TTypeVar 永远不会接受抽象类。
我见过的唯一明智的解决方案是禁用此错误,例如通过将其包含在文件中mypy.ini:
[mypy]\n# Allows Type[T] to refer to abstract classes, which is not otherwise supported.\n# See https://github.com/python/mypy/issues/4717\ndisable_error_code = type-abstract\nRun Code Online (Sandbox Code Playgroud)\n引用讨论:
\n\n\n既然 #14619 已合并,默认情况下禁用类型抽象错误代码是否可以解决所有主要问题,或者是否还需要做其他事情?
\n
我稍后会将我的 2\xc2\xa2 添加到票证中,希望他们能解决这个问题。
\n| 归档时间: |
|
| 查看次数: |
1369 次 |
| 最近记录: |