Python 3.x Python类型:使用泛型类型创建类函数,并通过类访问该类型

Python 3.x Python类型:使用泛型类型创建类函数,并通过类访问该类型,python-3.x,typing,python-typing,Python 3.x,Typing,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

我有一个发布者,可以发布特定类型的邮件:

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)
这是可行的,publish函数具有正确的类型提示,但我希望能够使用
get\u 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)
但这需要在
p=Publisher[int](int,“chatter”)
行中写入两次
int
,这似乎有点笨拙和多余

我尝试将发布服务器的创建包装到一个函数中,这样您就不必写两次
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
所以我需要的是一个方法,在typehint上下文中将
Type[x]
转换为
x
。本质上与
类型的功能相反

e、 g,最后一个例子是:

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)
但是我不知道如何使
实例通用

还有什么我可以做的吗?或者以任何其他方式获得我想要的功能,而不必在
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
我有一个基于的答案,但它取决于未记录的实现细节

from typing import TypeVar, Generic, get_args, get_origin

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(self.__orig_class__)[0]

p = Publisher[int]("hello")
print(p.get_type())

显式传入类型,但将其注释为
type[T]
。这允许在不必指定的情况下推断
T
,使其足以只指定一次类型(作为参数)

类发布器(通用[T]): #知道“msg_type”定义了“T”` 定义初始化(self,消息类型:type[T],主题:str)->None: self.\u msg\u type=msg\u type self.\u topic=主题 def发布(self,msg:T): 通过 def get_类型(自身)->类型[T]: 返回self.\u msg\u类型 #'int'的参数意味着T=int p=发布者(int,“hello”) 打印(p.get_type())# 如果类型_检查: 显示类型(p)#注意:显示类型为“aaa_testbed.Publisher[builtins.int*]”
您能解释一下为什么需要
[int]
零件吗。这似乎是多余的,没有它就无法编写代码。@venky_uuu我不确定我是否理解。
int
就是一个例子。可以使用任何类型创建发布服务器。这回答了你的问题吗?不,我的意思是
Publisher[int](int,“chatter”)
可以写成
Publisher(int,“chatter”)
。如果没有,那么为什么?@venky\uuuu。我想在运行前使用
mypy
捕捉类型错误。
Publisher[int]
[int]
确保从现在起,只能使用int调用Publisher
publish
函数。如果没有此功能,我将不得不在publish函数中执行runtme检查,以检查是否使用正确的类型调用了它。相关: