假设您有一个从泛型[T]继承的Python类.有没有办法获取从类/实例中传入的实际类型?

例如

from typing import TypeVar, Type
T = TypeVar('T')

class Test(Generic[T]):
    def hello(self):
      my_type = T  # this is wrong!
      print( "I am {0}".format(my_type) )

Test[int]().hello() # should print "I am int"

here上,建议类型arg出现在该类型的args字段中.事实上,

print( str( Test[int].__args__ ) )

将打印(<class'int'>,).然而,我似乎无法直接从实例中访问它,例如替换

      my_type = self.__class__.__args__ # this is also wrong (None)

这似乎不对劲.

谢谢

推荐答案

没有支持此操作的API.在有限的情况下,如果您愿意处理未记录的实现细节,您有时可以这样做,但这根本不可靠.


首先,在为泛型变量赋值时,mypy不需要提供类型参数.你可以做像x: Test[int] = Test()这样的事情,Python和mypy都不会抱怨.mypy推断类型参数,但在运行时使用Test而不是Test[int].由于显式类型参数难以编写,并且会带来性能损失,因此许多代码只在注释中使用类型参数,而不是在运行时使用.

无法在运行时恢复从未在运行时提供的类型参数.


要在运行时完全保留内部参数,请注意,如果当前未记录此属性,则可能仅在运行时提供does个内部参数.具体来说,当你打电话的时候

Test[int]()

,新对象的类是Test而不是Test[int],但typing实现试图设置

obj.__orig_class__ = Test[int]

在新物体上.如果它不能设置__orig_class__(例如,如果Test使用__slots__),那么它将捕获AttributeError并放弃.

Python 3.5.3中引入了__orig_class__;3.5.2及更低版本中不存在.typing中没有任何内容实际使用__orig_class__.

__orig_class__赋值的时间因Python版本而异,但目前,在正常对象构造完成后,时间是set.您将无法在__init____new__期间判断__orig_class__.

从CPython 3.8.2开始,这些实施细节是最新的.


__orig_class__是一个实现细节,但至少在Python3.8上,您不必访问任何其他实现细节来获取类型参数.Python3.8引入了typing.get_args,它返回typing类型的类型参数的元组,或返回无效参数的().(是的,从Python3.5到3.8,一直没有公开的API.)

例如

typing.get_args(Test[int]().__orig_class__) == (int,)

如果有__orig_class__个,并且你愿意访问它,那么__orig_class__get_args一起提供你想要的.

Python-3.x相关问答推荐

如何定义既允许固定单词又允许模式的pydanti.BaseModel?

Django内置注销视图`不允许的方法(GET):/USERS/LOGOUT/`

为什么我在BLE中的广告代码在发送包裹之间需要大约1秒

我用Kivy创建的应用程序在安卓系统上运行时出错.(attributeerror:';class';对象没有属性';_javaclass__cls_storage';)

错误:无法为 pyconcorde 构建轮子,这是安装基于 pyproject.toml 的项目所必需的

对大型数据框中的选定列进行重新排序

在REPLACE INTO中引用变量会抛出sqlite3.OperationalError

如何将日期时间索引写入日期类型的表?

使用 RANSAC 在激光雷达点云中查找电力线

Python - 如何从同一台客户端机器运行多个Flask应用程序

二进制文件的 Python 3 和 base64 编码

django rest框架中的save()、create()和update()有什么区别?

如何禁用 pylint 禁止自用警告?

使用 Sympy 方程进行绘图

Python3 mysqlclient-1.3.6(又名 PyMySQL)的用法?

作为函数对象属性的 __kwdefaults__ 有什么用?

类型提示返回 NameError: name 'datetime' not defined

python判断一个方法是否被调用而不模拟它

python中的订单字典索引

TypeError:无法将系列转换为