如何解决如何定义一个不是类的泛型类型?
我想定义一个泛型类型。类似的东西:
T = TypeVar('T')
RecurSeqOf = Sequence[Union[Generic[T],Sequence[T]]]
# mypy error: Variable "typing.Generic" is not valid as a type
有办法吗?
整个背景
实际上,我需要一个递归泛型类型
T = TypeVar('T')
RecurSeqOf = Sequence[Union[T,'RecurSeqOf']]]
但是mypy还不支持递归类型的定义:https://github.com/python/mypy/issues/731
这就是为什么我通过使嵌套类型定义达到有限的深度来解决这个问题(例如,通常是 5-6 级,但在下面两个级别的示例中只是为了简洁起见)。 因此,更需要缩短模式,因为我需要将它用于不同的参数类型:
from typing import Sequence,Union,TypeVar,Generic
class A:
pass
class B:
pass
# RecurSeqOfA = Sequence[Union[A,'RecurSeqOfA']] # mypy error: Cannot resolve name "RecurSeqOfA" (possible cyclic definition)
RecurSeqOfA = Sequence[Union[A,Sequence[Union[A,Sequence[A]]]]]
# RecurSeqOfA = Sequence[Union[A,'RecurSeqOfA']] # mypy error: Cannot resolve name "RecurSeqOfA" (possible cyclic definition)
RecurSeqOfB = Sequence[Union[B,Sequence[Union[B,Sequence[B]]]]]
T = TypeVar('T')
# RecurSeqOf = Sequence[Union[Generic[T],'RecurSeqOf']] # error: Cannot resolve name "RecurSeqOf" (possible cyclic definition)
# additionally: error: Variable "typing.Generic" is not valid as a type
RecurSeqOf = Sequence[Union[Generic[T],Sequence[Generic[T]]]] # error: Variable "typing.Generic" is not valid as a type
正如 MisterMiyagi 的评论所建议的:
from typing import TypeVar,MutableSequence
T = TypeVar('T',bound='RecurSeqOf')
RecurSeqOf = MutableSequence[T]
a: RecurSeqOf[str] = []
a.append("abc")
a.append([]) # mypy error: error: Argument 1 to "append" of "MutableSequence" has incompatible type "List[<nothing>]"; expected "str"
b: RecurSeqOf[str] = []
a.append(b) # mypy error: Argument 1 to "append" of "MutableSequence" has incompatible type "MutableSequence[str]"; expected "str"
a.append(["cde"]) # mypy error: Argument 1 to "append" of "MutableSequence" has incompatible type "List[str]"; expected "str"
定义本身被 mypy 接受。但是没有达到预期的效果。
解决方法
既然 Sequence
已经是泛型了,可以直接使用类型变量:
from typing import TypeVar,Sequence,Union
T = TypeVar('T')
# [T,...] | [[T,...],...]
RecurSeqOf = Sequence[Union[T,Sequence[T]]]
# T | [T,...]
RecurSeqOfUnion = Union[RecurSeqOf[T],T]
这就是 the documentation 所说的“用户定义的泛型类型别名”。 RecurSeqOf = ...
定义了别名,而 Sequence[Union[T,Sequence[T]]]
是通用的。
这允许定义固定但任意深度的递归类型:
a0: RecurSeqOf[int]
a1: RecurSeqOf[RecurSeqOfUnion[int]]
a2: RecurSeqOf[RecurSeqOfUnion[RecurSeqOfUnion[int]]]
reveal_type(a0) # typing.Sequence[Union[builtins.int,typing.Sequence[builtins.int]]]
reveal_type(a1) # typing.Sequence[Union[typing.Sequence[Union[builtins.int,typing.Sequence[builtins.int]]],builtins.int,typing.Sequence[Union[typing.Sequence[Union[builtins.int,builtins.int]]]]
reveal_type(a2) # typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int,builtins.int]]]],typing.Sequence[Union[builtins.int,typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int,builtins.int]]]]
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。