python类是实例的工厂_Python 3类型提示,用于返回子类实例的基类上的工厂方法

假设我在Base中有两个类Base和Child.工厂方法调用另一个类方法,它可以被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()返回Child的实例,以便以下示例将传递静态分析?

base = Base.create(1)

child = Child.create(2, 3)

child.method_not_present_on_base()

在上面的示例中,静态类型检查器会正确地抱怨method_not_present_on_base在Base类中不存在.

我想过将Base转换为泛型类,让子类将自己指定为类型参数,即将CRTP引入Python.

T = TypeVar('T')

class Base(Generic[T]):

@classmethod

def create(cls, *args: Tuple) -> T: ...

class Child(Base['Child']): ...

但是这种感觉相当单一,而CRTP来自C和所有……

解决方法:

这确实是可能的:该功能被称为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': ...

注意:

>我们不需要使类本身通用,因为我们只需要一个泛型函数

>将TypeVar绑定到’Base’严格来说是可选的,但这可能是个好主意:这样,基类/子类的调用者至少能够调用基类中定义的方法,即使你没有’我确切地知道你正在处理哪个子类.

>我们可以省略子定义的cls上的注释.

标签:python,python-3-x,type-hinting

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值