首页 > 解决方案 > Python Typing:创建一个具有泛型类型的类函数,并通过该类访问该类型

问题描述

我有一个发布者可以发布某种类型的消息:

T = TypeVar('T')
class Publisher(Generic[T]):

    def __init__(self, topic: str) -> None:
        self.__topic = topic

    def publish(self, msg: T):
        pass

# As an example, create a publisher that can publish ints
p = Publisher[int]("chatter")
p.publish(1)

这可行,并且发布函数具有正确的类型提示,但我希望能够使用get_type()函数访问发布者的类型。

一种简单的方法是将消息类型传递给构造函数:

T = TypeVar('T')
class Publisher(Generic[T]):

    def __init__(self, msg_type: type, topic: str) -> None:
        self.__msg_type = msg_type
        self.__topic = topic

    def publish(self, msg: T):
        pass

    def get_type(self) -> type:
        return self.__msg_type

p = Publisher[int](int, "chatter")
p.publish(1)

但这需要int在一行中写两次,p = Publisher[int](int, "chatter")这似乎有点笨拙和多余。

我尝试将发布者的创建包装在一个函数中,这样您就不必编写int两次,但我遇到了一个问题:

T = TypeVar('T', bound=type)
class Publisher(Generic[T]):

    def __init__(self, msg_type: type, topic: str) -> None:
        self.__msg_type = msg_type
        self.__topic = topic

    def publish(self, msg: T):
        pass

    def get_type(self) -> type:
        return self.__msg_type

def create_publisher(msg_type: T, topic: str) -> Publisher[T]:
    return Publisher[T](msg_type, topic)

p = create_publisher(int, "hello")

p.publish(1) #Fails because its expecting Type[int], not an instance of an int

所以我需要的是一种在类型提示上下文中转换Type[x]为的方法。x基本上与做什么相反Type

例如,最后一个示例将变为:

T = TypeVar('T', bound=type)
class Publisher(Generic[T]):

    def __init__(self, msg_type: type, topic: str) -> None:
        self.__msg_type = msg_type
        self.__topic = topic

    def publish(self, msg: InstanceOf[T]):
        pass

    def get_type(self) -> type:
        return self.__msg_type

def create_publisher(msg_type: T, topic: str) -> Publisher[T]:
    return Publisher[T](msg_type, topic)

p = create_publisher(int, "hello")

p.publish(1)

但我不知道如何使InstanceOf通用。

无论如何我可以做到这一点吗?或任何其他方式来获得我想要的功能,而不必int在一行中写两次p = Publisher[int](int, "chatter")

编辑

这是另一种也不起作用的尝试,但应该澄清我正在尝试做的事情:

T = TypeVar('T')
class Publisher(Generic[T]):

    def __init__(self, topic: str) -> None:
        self.__topic = topic

    def publish(self, msg: T):
        pass

    def get_type(self) -> type:
        return get_args(Publisher[T])[0]

#This works
print(get_args(Publisher[int])[0])

#This doesn't
p = Publisher[int]("hello")
print(p.get_type())

在这个例子中p.get_type()返回~T而不是int

标签: python-3.xtype-hintingpython-typing

解决方案


显式传入类型,但将其注释为Type[T]. T这允许在不必指定它的情况下进行推断,使得只需指定一次类型(作为参数)就足够了。

class Publisher(Generic[T]):
    # knowing `msg_type` defines `T`
    def __init__(self, msg_type: Type[T], topic: str) -> None:
        self._msg_type = msg_type
        self._topic = topic

    def publish(self, msg: T):
        pass

    def get_type(self) -> Type[T]:
        return self._msg_type


# argument of `int` implies T = int
p = Publisher(int, "hello")
print(p.get_type())  # <class 'int'>
if TYPE_CHECKING:
    reveal_type(p)   # note: Revealed type is 'aaa_testbed.Publisher[builtins.int*]'

推荐阅读