如何访问typing.Generic的类型参数?

Ara*_*Fey 22 python generics

typing模块为泛型类型提示提供了一个基类:typing.Generic该类.

Generic方括号中的accept类型参数的子类,例如:

list_of_ints = typing.List[int]
str_to_bool_dict = typing.Dict[str, bool]
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何访问这些类型的参数?

也就是说,str_to_bool_dict作为输入,我如何得到strbool作为输出?

基本上我正在寻找一个这样的功能

>>> magic_function(str_to_bool_dict)
(<class 'str'>, <class 'bool'>)
Run Code Online (Sandbox Code Playgroud)

c z*_*c z 19

可能性1

从Python 3.6开始.有一个公共__args__和(__parameters__)字段.例如:

print( typing.List[int].__args__ )
Run Code Online (Sandbox Code Playgroud)

这包含通用参数(即int),同时__parameters__包含通用本身(即~T).

可能性2

使用typing_inspect.getargs

使用哪种

typing遵循PEP8.PEP8和typingGuido van Rossum共同合着.双引导和尾随下划线定义为:""魔术"对象或属于用户控制的命名空间的属性".

dunders也在线评论; 从官方的资料库输入,我们可以看到:*" __args__是下标中使用的所有参数,例如元组Dict[T, int].__args__ == (T, int)".

但是,作者还注意到:*"打字模块具有临时状态,因此它不符合高标准的向后兼容性(虽然我们尽可能地保持它),但对于(尚未记录的)尤其如此dunder属性如__union_params__.如果你想在运行时上下文中使用输入类型,那么你可能对该typing_inspect项目感兴趣(其中一部分最终可能会在以后输入)."

总的来说,无论你做什么,typing都需要暂时保持最新状态.如果您需要向前兼容的更改,我建议您编写自己的注释类.

  • 你怎么知道这是公开的?如果您有任何消息来源,请引用它们. (3认同)
  • "你怎么知道这是公开的" - 因为`__xxx__`总是公开的,不像`_xxx`和`__xxx`从来没有暗示过.我认为你的意思是"你怎么知道这是记录在案的".我用文档更新了我的答案. (2认同)

Pet*_*ris 5

似乎这种内部方法可以解决问题

typing.List[int]._subs_tree()
Run Code Online (Sandbox Code Playgroud)

返回元组:

(typing.List, <class 'int'>)
Run Code Online (Sandbox Code Playgroud)

但这是一个私有API,可能有更好的答案.


Jac*_*din 5

据我所知,这里没有幸福的答案。

我想到的是__args__未记录的属性,用于存储以下信息:

list_of_ints.__args__
>>>(<class 'int'>,)

str_to_bool_dict.__args__
>>>(<class 'str'>, <class 'bool'>)
Run Code Online (Sandbox Code Playgroud)

但是typing模块文档中没有提及它。

值得注意的是,尽管在文档中提到的内容非常接近

也许我们还应该讨论是否需要记录的所有关键字参数GenericMeta.__new__。有tvarsargsoriginextra,和orig_bases。我认为,我们可以谈谈前三(它们对应于__parameters____args____origin__这些在打字使用的最多的事)。

但是它并没有做到

我加入GenericMeta__all__并添加文档字符串来GenericMetaGenericMeta.__new__下面的问题的讨论。我决定不以__origin__文档字符串形式描述和朋友。相反,我只是在第一次使用它们的地方添加了评论。

从那里开始,您仍然有三个非互斥选项:

  • 等待typing模块完全成熟,并希望这些功能能尽快记录在案

  • 加入Python想法邮件列表,查看是否可以收集到足够的支持以使这些内部结构公开/成为API的一部分

  • 同时使用未公开的内部文件进行赌博,赌博不会对这些文件进行任何更改,或者更改将很小。

请注意,第三点很难避免,因为即使API也会发生变化

键入模块已临时包含在标准库中。如果核心开发人员认为必要,则可能会添加新功能,并且即使在次要发行版之间API也会更改