您可以使用标准库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'
如果可以的话,我会避免返回联合类型.