如何在Python中通过反射获取类的@property属性并映射类型
如何通过反射读取@property的类型注释并构建映射
嘿,这个需求其实挺实用的,不管是做类型校验还是自动生成文档都能用得上。我来给你讲清楚具体的实现思路和代码:
核心思路拆解
要实现这个目标,我们需要做两件关键的事:
- 先从类里筛选出所有被
@property装饰的属性 - 然后解析每个property的getter方法里的类型注释,提取出箭头后面的类型字符串
具体代码实现
首先我们要用到inspect模块来获取函数的源代码,再用正则表达式匹配注释里的类型信息。直接上代码:
import inspect import re from typing import Dict def get_property_type_map(cls) -> Dict[str, str]: property_type_map = {} # 遍历类自身定义的所有成员(避免拿到父类继承来的属性) for attr_name, attr_value in vars(cls).items(): # 判断当前成员是不是@property对象 if isinstance(attr_value, property): # 获取property对应的getter方法 getter_method = attr_value.fget try: # 拿到getter方法的源代码行 source_lines = inspect.getsourcelines(getter_method)[0] except OSError: # 如果无法获取源代码(比如动态生成的方法),直接跳过 continue # 用正则匹配类型注释行 type_comment_pattern = re.compile(r'# type: \(.*\) -> (.*)') for line in source_lines: stripped_line = line.strip() match_result = type_comment_pattern.match(stripped_line) if match_result: # 提取并保存类型字符串 property_type_map[attr_name] = match_result.group(1).strip() break # 找到注释就不用继续遍历了 return property_type_map
测试一下
假设你的MyClass已经定义好了,直接调用这个函数就行:
result = get_property_type_map(MyClass) print(result) # 输出就是你想要的: {'property1': 'pb.data.Property1', 'property2': 'pb.data.Property2'}
额外说明
- 为什么用
vars(cls)而不是dir(cls)?因为dir()会返回类继承来的所有属性,而vars()只返回当前类自己定义的成员,这样能避免把父类的property也混进来。如果需要包含父类的属性,可以遍历cls.__mro__(方法解析顺序)来逐个处理。 - 正则表达式是严格匹配你给出的注释格式
# type: () -> 类型,如果你的注释格式有变化,比如括号里有内容,或者空格不一样,稍微调整正则就行。 - 如果你的代码是用Python 3.6+的类型注解(不是注释形式),比如:
那可以直接用@property def property1(self) -> pb.data.Property1: passinspect.signature(getter_method).return_annotation来获取类型,这种方式更可靠,不用解析注释~
内容的提问来源于stack exchange,提问作者rajan sthapit
相关产品推荐
相关产品推荐

