如何定义不是 class 的泛型类型?
How to define a generic type that is not a class?
我想定义一个通用类型。类似于:
from typing import TypeVar, Sequence, Union, Generic
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']]]
但是递归类型的定义是not yet supported mypy.
这就是为什么我通过使嵌套类型定义达到有限深度(例如,通常为 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, ...] | [[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, typing.Sequence[builtins.int]]], builtins.int]]]]
reveal_type(a2) # typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]], typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]], typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]]
我想定义一个通用类型。类似于:
from typing import TypeVar, Sequence, Union, Generic
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']]]
但是递归类型的定义是not yet supported mypy.
这就是为什么我通过使嵌套类型定义达到有限深度(例如,通常为 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, ...] | [[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, typing.Sequence[builtins.int]]], builtins.int]]]]
reveal_type(a2) # typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]], typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int, typing.Sequence[Union[typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]], typing.Sequence[Union[builtins.int, typing.Sequence[builtins.int]]], builtins.int]]]]