[英]How should I type-hint a generic class method that calls another class method to construct an instance of the class?
我试图找出几个抽象类的类型提示,我想将它们用作类的基类, create
function。具体来说,这是用于反序列化类型。
我的简单示例如下所示
from abc import ABC, abstractmethod
from typing import Type, TypeVar
T = TypeVar("T", bound="A")
class A(ABC):
@classmethod
@abstractmethod
def create(cls: Type[T]) -> T:
pass
class B(A, ABC):
@classmethod
@abstractmethod
def create_b(cls: Type[T]) -> T:
pass
@classmethod
def create(cls) -> T:
return cls.create_b()
当我针对这个运行 Mypy 时,我得到
错误:不兼容的返回值类型(得到“B”,应为“T”)
我对此感到困惑,因为B
继承自A
,我认为T
或多或少代表“任何A
”。
我可以将倒数第二行更改为
def create(cls: Type[T]) -> T:
但后来我明白了
错误:“Type[T]”没有属性“create_b”
我应该怎么做才能让 mypy 通过?
由于create
是 class 方法,因此参数cls
的类型为Type[B]
。 这意味着create_b
中为参数和返回类型指定的T
将解析为B
,因此表达式cls.create_b()
的类型为B
这会导致您收到错误。
这里令人困惑的部分可能是因为B
是A
的子类型并且T
绑定到A
,所以人们可能期望应该可以在B.create()
中返回B
。 然而,问题是,当B.create()
在某些上下文中使用而不是更早时, T
将得到解决。 在您的示例中,您已经隐式地将T
强制为B
,这可能会导致类型错误。
例如,假设我们创建以下 class 和 function。
class C(A):
pass
def foo(x: C):
pass
我们现在可以使用B.create()
作为foo
的参数:
foo(B.create())
类型检查器不会在这里抱怨,因为它解析T
( create
的通用返回类型为C
,这非常好,因为T
由A
绑定,而C
是A
的子类型。
重新审视B.create()
的 function 定义,我们现在可以看到我们实际上必须返回抽象类型T
而不是T
的某些允许的实现,例如B
(甚至A
)。
您可以通过更改B.create()
的返回类型来修复错误:
@classmethod
def create(cls) -> "B":
return cls.create_b()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.