Python 3 类型,具有任意数量包含类型的自定义可变参数泛型类型,如何实现?

问题描述 投票:0回答:2

typing.Tuple
可以与任意数量的类型参数一起使用,例如
Tuple[int, str, MyClass]
Tuple[str, float]
。我如何实现我自己的可以像这样使用的类?我明白了如何继承
typing.Generic
。以下代码演示了这一点。

from typing import TypeVar, Generic


T = TypeVar("T")


class Thing(Generic[T]):
    def __init__(self, value: T):
        self.value = value


def f(thing: Thing[int]):
    print(thing.value)


if __name__ == '__main__':
    t = Thing("WTF")
    f(t)

上面的代码可以工作,但是类型检查器(在我的例子中是 PyCharm)会发现

t
应该是
Thing[int]
类型而不是
Thing[str]
类型。一切都很好,但是如何让类
Thing
支持任意数量的类型参数,就像
Tuple
那样?

python-3.x types typing variadic
2个回答
0
投票

就像@metatoaster在他们的评论中所说,这可以使用

TypeVarTuple
,从3.11开始在
typing
中可用,以及
typing_extensions
,否则:

from typing import Generic, TypeVarTuple

Ts = TypeVarTuple("Ts")


class Thing(Generic[*Ts]):
    def __init__(self, *value: *Ts):
        self.value = value


def f(thing: Thing[int]):
    print(thing.value)


t = Thing("WTF")  # Type of "t" is "Thing[str]"
f(t)  # error: Type parameter "Ts@Thing" is invariant, but "*tuple[str]" is not the same as "*tuple[int]"

-4
投票
  • 在您的示例中,
    t
    的类型为
    Thing
    ,而不是
    Thing[str]
    。所以这个对象接受任何
    T
  • 您可以像这样对其进行参数化:
    t2 = Thing[str]("WTF")
  • 现在,对于你的问题,我认为你想像这样使用 typing.Union
    t3=Thing[Union[str,int,float]]("WTF")

顺便说一句,您可以使用 typing_inspect

中的 get_generic_type() 检查泛型的类型
>>> get_generic_type(t)
__main__.Thing
>>> get_generic_type(t2)
__main__.Thing[str]
>>> get_generic_type(t3)
__main__.Thing[typing.Union[str, int, float]]
© www.soinside.com 2019 - 2024. All rights reserved.