使用受限的 TypeVar 继承泛型 类
Inheriting Generic classes with restricted TypeVar
考虑一对简单的泛型 类:
T = TypeVar("T", str, int)
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
使用 T = TypeVar("T")
时按预期工作。如图所示,受限制的 TypeVar
会产生以下错误:
error: Argument 1 to "__init__" of "Base" has incompatible type "str"; expected "T"
error: Argument 1 to "__init__" of "Base" has incompatible type "int"; expected "T"
note: Revealed type is 'builtins.int*'
请注意 reveal_type
仍然有效。
另一个区别是,受限制的 TypeVar
需要类型注释才能进行 self.v
赋值,而不受限制的则不需要。
在完整的用例中,我实际上有 Callable[[Any], T]
,但问题是一样的。
这是 mypy 0.910
和 Python 3.9.7
。
这似乎在您调用 super()
并将通用受限 TypeVar
参数传递给任何函数而不仅仅是 init 时发生。在这些情况下,我相信我们可以通过在这些行中包含 # type: ignore
来要求 mypy 保留这个可怜的东西:
...
super().__init__(v) # type: ignore
...
它并没有看起来那么糟糕,因为类型检查仍将在其他行上进行,这与从父函数或子函数的参数中删除 : T
时发生的情况不同 (这些中的任何一个都足以抑制抱怨,但也会停止检查这些函数内部。
将 T
绑定到 Union[int,str]
应该可以完成工作:
T = TypeVar("T", bound=Union[str, int])
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
y = Child('a')
reveal_type(y.value)
考虑一对简单的泛型 类:
T = TypeVar("T", str, int)
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
使用 T = TypeVar("T")
时按预期工作。如图所示,受限制的 TypeVar
会产生以下错误:
error: Argument 1 to "__init__" of "Base" has incompatible type "str"; expected "T"
error: Argument 1 to "__init__" of "Base" has incompatible type "int"; expected "T"
note: Revealed type is 'builtins.int*'
请注意 reveal_type
仍然有效。
另一个区别是,受限制的 TypeVar
需要类型注释才能进行 self.v
赋值,而不受限制的则不需要。
在完整的用例中,我实际上有 Callable[[Any], T]
,但问题是一样的。
这是 mypy 0.910
和 Python 3.9.7
。
这似乎在您调用 super()
并将通用受限 TypeVar
参数传递给任何函数而不仅仅是 init 时发生。在这些情况下,我相信我们可以通过在这些行中包含 # type: ignore
来要求 mypy 保留这个可怜的东西:
...
super().__init__(v) # type: ignore
...
它并没有看起来那么糟糕,因为类型检查仍将在其他行上进行,这与从父函数或子函数的参数中删除 : T
时发生的情况不同 (这些中的任何一个都足以抑制抱怨,但也会停止检查这些函数内部。
将 T
绑定到 Union[int,str]
应该可以完成工作:
T = TypeVar("T", bound=Union[str, int])
class Base(Generic[T]):
def __init__(self, v: T):
self.v: T = v
@property
def value(self) -> T:
return self.v
class Child(Base[T]):
def __init__(self, v: T):
super().__init__(v)
x = Child(123)
reveal_type(x.value)
y = Child('a')
reveal_type(y.value)