假设我在Base
中有两个类Child
和Base
的工厂方法。工厂方法调用另一个类方法,可以被Base
的子类覆盖。
class Base(object):
@classmethod
def create(cls, *args: Tuple) -> 'Base':
value = cls._prepare(*args)
return cls(value)
@classmethod
def _prepare(cls, *args: Tuple) -> Any:
return args[0] if args else None
def __init__(self, value: Any) -> None:
self.value = value
class Child(Base):
@classmethod
def _prepare(cls, *args: Tuple) -> Any:
return args[1] if len(args) > 1 else None
def method_not_present_on_base(self) -> None:
pass
是否有办法注释Base.create
,以便静态类型检查器可以推断Base.create()
返回Base
的实例,而Child.create()
返回{{1}的实例,以便以下示例将传递静态分析?
Child
在上面的示例中,静态类型检查器会理所当然地抱怨base = Base.create(1)
child = Child.create(2, 3)
child.method_not_present_on_base()
类上没有method_not_present_on_base
。
我考虑过将Base
转换为泛型类,并让子类将自己指定为类型参数,即将CRTP引入Python。
Base
但是CRTP来自C ++并且所有人都感到相当不熟悉......
答案 0 :(得分:5)
确实有可能:该功能被称为TypeVar with Generic Self(虽然这有点误导,因为我们在这种情况下将其用于类方法)。我相信它的行为大致相当于" CRTP"你联系到的技术(虽然我不是C ++专家所以不能肯定地说)。
在任何情况下,您都会声明您的基类和子类:
from typing import TypeVar, Type, Tuple
T = TypeVar('T', bound='Base')
class Base:
@classmethod
def create(cls: Type[T], *args: Tuple[Any]) -> T: ...
class Child(Base):
@classmethod
def create(cls, *args: Tuple[Any]) -> 'Child': ...
请注意:
cls
上省略子注释的注释。