如何获取Python内置方法的类型注解字符串?
获取Python内置方法的类型注解
问题根源
像str这种内置类型的方法是用C实现的,运行时的__annotations__属性是空的——PyCharm悬浮显示的类型注解,其实来自Python的标准库类型存根文件(.pyi),不是从运行时对象里直接读取的。
解决方法
1. 找到类型存根文件的位置
Python安装目录下的Lib/typeshed/stdlib文件夹里,每个内置类型都对应一个.pyi存根文件,比如str的存根就是str.pyi。如果找不到,可能需要先通过pip install typeshed安装官方存根库。
2. 提取注解的两种方式
方式一:正则匹配(快速简单)
直接读取存根文件内容,用正则匹配方法的签名:
import os import re def get_stub_method_signatures(obj_type): stub_name = f"{obj_type.__name__}.pyi" # 优先找Python自带的存根路径,找不到就用typeshed包的路径 stub_paths = [ os.path.join(os.path.dirname(os.__file__), "typeshed", "stdlib", stub_name), os.path.join(os.path.dirname(__file__), "venv", "lib", "python3.x", "site-packages", "typeshed", "stdlib", stub_name) ] stub_path = None for path in stub_paths: if os.path.exists(path): stub_path = path break if not stub_path: return {} with open(stub_path, 'r', encoding='utf-8') as f: content = f.read() signatures = {} # 筛选出非私有方法 method_names = [name for name in dir(obj_type) if not name.startswith('_')] for method in method_names: # 匹配方法定义行(支持跨行的参数列表) pattern = rf"def {method}\((?:.|\n)*?\) -> (?:.|\n)*?:" match = re.search(pattern, content) if match: # 去掉换行符,整理成单行 signatures[method] = ' '.join(match.group().split()) return signatures # 测试获取str.upper的签名 print(get_stub_method_signatures(str).get('upper'))
方式二:AST解析(严谨可靠)
用Python的ast模块解析存根文件的语法树,精准提取方法签名:
import os import ast def get_method_signatures_via_ast(obj_type): stub_name = f"{obj_type.__name__}.pyi" stub_paths = [ os.path.join(os.path.dirname(os.__file__), "typeshed", "stdlib", stub_name), os.path.join(os.path.dirname(__file__), "venv", "lib", "python3.x", "site-packages", "typeshed", "stdlib", stub_name) ] stub_path = None for path in stub_paths: if os.path.exists(path): stub_path = path break if not stub_path: return {} with open(stub_path, 'r', encoding='utf-8') as f: tree = ast.parse(f.read()) signatures = {} method_names = set(dir(obj_type)) for node in ast.walk(tree): if isinstance(node, ast.FunctionDef) and node.name in method_names and not node.name.startswith('_'): # 拼接参数部分 args_list = [] # 处理self参数 if node.args.args: self_arg = node.args.args[0] self_str = self_arg.arg if self_arg.annotation: self_str += f": {ast.unparse(self_arg.annotation)}" args_list.append(self_str) # 处理其他参数 for arg in node.args.args[1:]: arg_str = arg.arg if arg.annotation: arg_str += f": {ast.unparse(arg.annotation)}" args_list.append(arg_str) # 处理返回值注解 return_anno = ast.unparse(node.returns) if node.returns else "" # 拼接完整签名 signature = f"def {node.name}({', '.join(args_list)})" if return_anno: signature += f" -> {return_anno}:" signatures[node.name] = signature return signatures # 测试 print(get_method_signatures_via_ast(str).get('upper'))
额外说明
- 自定义Python类的方法,直接访问
obj.method.__annotations__就能拿到类型注解,只有C实现的内置方法需要读存根文件。 - 不同Python版本的存根文件路径可能有差异,需要根据自己的环境调整路径。
内容的提问来源于stack exchange,提问作者Benedict Abub
相关产品推荐
相关产品推荐

