我有一个表示对象类型的字符串,在本例中总是一个元组,格式与使用类型提示编写的格式一致. 所以像这样的东西,

Tuple[int, int]

我想列出元组中的类型列表.不幸的是,我们的简单正则表达式失败了,因为它不能处理对象内部的类型本身是集合或联合的情况.理想情况下,我应该能够拿到这样的东西:

Tuple[Union[file.File, directory.Directory, Tuple[file.File, directory.Directory]], Tuple[file.File, directory.Directory]]

并返回一个包含两个元素的列表:

Union[file.File, directory.Directory, Tuple[file.File, directory.Directory]]
Tuple[file.File, directory.Directory]

但是,使用正则表达式和字符串操作来实现这一点似乎既丑陋又凌乱.这肯定是一个已经出现的用例,并且已经有一些库可以处理像这样的拆分输入?

推荐答案

您可以使用标准库ast模块中提供的内置Python解析器.某物的效果是:

import ast
def extract_tuple_hints(string: str) -> list[str]:
    exp = ast.parse(string, mode="eval")
    if not isinstance(exp.body, ast.Subscript):
        raise ValueError("Expecting a subscript expression, e.g. 'Tuple[...]'")
    lines = string.splitlines()
    return [
        lines[e.lineno-1][e.col_offset:e.end_col_offset]
        for e in exp.body.slice.elts
    ]

注意,这假设订阅表达式有多个元素,所以Tuple[foo, bar],如果你想处理类似Tuple[foo]的情况,那么你会有一些稍微混乱的东西:

import ast
def extract_tuple_hints(string: str) -> list[str] | str:
    exp = ast.parse(string, mode="eval")
    if not isinstance(exp.body, ast.Subscript):
        raise ValueError("Expecting a subscript expression, e.g. 'Tuple[...]'")
    lines = string.splitlines()
    slice_ = exp.body.slice
    if isinstance(slice_, ast.Tuple):
        return [
            lines[e.lineno-1][e.col_offset:e.end_col_offset]
            for e in slice_.elts
        ]
    else:
        return lines[slice_.lineno-1][slice_.col_offset:slice_.end_col_offset]

因此,在行动中:

In [3]: import ast
   ...: def extract_tuple_hints(string: str) -> list[str] | str:
   ...:     exp = ast.parse(string, mode="eval")
   ...:     if not isinstance(exp.body, ast.Subscript):
   ...:         raise ValueError("Expecting a subscript expression, e.g. 'Tuple[...]'")
   ...:     lines = string.splitlines()
   ...:     slice_ = exp.body.slice
   ...:     if isinstance(slice_, ast.Tuple):
   ...:         return [
   ...:             lines[e.lineno-1][e.col_offset:e.end_col_offset]
   ...:             for e in slice_.elts
   ...:         ]
   ...:     else:
   ...:         return lines[slice_.lineno-1][slice_.col_offset:slice_.end_col_offset]
   ...:

In [4]: s = "Tuple[Union[file.File, directory.Directory, Tuple[file.File, directory.Directory]], Tuple[file.File, directory.Directory]]"

In [5]: extract_tuple_hints(s)
Out[5]:
['Union[file.File, directory.Directory, Tuple[file.File, directory.Directory]]',
 'Tuple[file.File, directory.Directory]']

In [6]: extract_tuple_hints("Tuple[int, str]")
Out[6]: ['int', 'str']

In [7]: extract_tuple_hints("Tuple[int]")
Out[7]: 'int'

如果可以的话,我会避免返回联合类型.

Python相关问答推荐

如何从具有多个嵌入选项卡的网页中Web抓取td类元素

我必须将Sigmoid函数与r2值的两种类型的数据集(每种6个数据集)进行匹配,然后绘制匹配函数的求导.我会犯错

在Python中对分层父/子列表进行排序

@Property方法上的inspect.getmembers出现意外行为,引发异常

我从带有langchain的mongoDB中的vector serch获得一个空数组

按顺序合并2个词典列表

从groupby执行计算后创建新的子框架

pandas在第1列的id,第2列的标题,第3列的值,第3列的值?

Plotly Dash Creating Interactive Graph下拉列表

numpy.unique如何消除重复列?

在不同的帧B中判断帧A中的子字符串,每个帧的大小不同

搜索按钮不工作,Python tkinter

如何获取Python synsets列表的第一个内容?

从一个df列提取单词,分配给另一个列

如何在GEKKO中使用复共轭物

当输入是字典时,`pandas. concat`如何工作?

将数据从一个单元格保存到Jupyter笔记本中的下一个单元格

对包含JSON列的DataFrame进行分组

当lambda函数作为参数传递时,pyo3执行

了解如何让库认识到我具有所需的依赖项