[英]How do you annotate the type of an abstract class with 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
運行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
請注意,如果沒有更多的工作,mypy 無法知道工廠函數創建了哪個具體類,它只會知道它與AbstractClass
兼容,如reveal_type
的輸出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
這是有效的,因為即使類不是從abc.ABC
繼承的, abc.ABC
也會檢查標有@abstractmethod
方法。 但請注意,如果您使用 python 執行程序,您將不會再收到關於實例化Bad
類而不實現其抽象方法的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.