值得一看
广告
彩虹云商城
广告

热门广告位

获取类中所有声明或类型化的参数

获取类中所有声明或类型化的参数

本文旨在提供一种使用 Python 反射机制获取类及其父类中所有声明或类型化的参数的方法。通过结合 inspect.get_annotations 和类的 __mro__ 属性,我们可以提取包括父类在内的所有类型注解,并将其组织成一个易于使用的字典。本文提供详细的代码示例和解释,帮助读者理解和应用这一技术。

使用 inspect.get_annotations 和 __mro__ 获取参数类型信息

Python 的 inspect 模块提供了强大的反射功能,其中 inspect.get_annotations 函数可以获取指定对象的类型注解。类的 __mro__ 属性则包含了类的继承关系,即方法解析顺序(Method Resolution Order)。结合这两个工具,我们可以遍历类的继承链,提取所有父类的类型注解。

以下是一个示例代码:

import inspect
from typing import Any, Optional, Dict
class Parent:
parent_param: str
parent_default: Optional[str] = None
@classmethod
def find_params_meta(cls) -> Dict[str, Any]:
params_meta = {}
for c in reversed(cls.__mro__):
if hasattr(c, '__annotations__'):
for k, v in inspect.get_annotations(c).items():
if k not in params_meta: # 避免子类覆盖父类同名参数的类型信息
params_meta[k] = {"types": [v]}
if hasattr(cls, k) and getattr(cls, k) != inspect._empty:
params_meta[k]["default"] = getattr(cls, k)
return params_meta
class Child(Parent):
child_param: str
_params_meta: Optional[Dict[str, Any]] = None
def __init__(self, parent_param: str, child_param: str):
self._params_meta = self.find_params_meta()
self.child_param = child_param
self.parent_param = parent_param
def __getattr__(self, name):
# 模拟未初始化的属性访问
raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
# 实例化对象并打印结果
child_instance = Child("parent param", "child param")
print(child_instance._params_meta)
# 断言
expected_result = {
"parent_param": {"types": [str]},
"parent_default": {"types": [str, type(None)], "default": None},
"child_param": {"types": [str]},
}
assert child_instance._params_meta == expected_result

代码解释:

  1. Parent 类和 Child 类: 定义了父类 Parent 和子类 Child,包含类型注解的类属性。
  2. find_params_meta 方法: 这是一个类方法,用于获取类及其父类的类型注解。
  3. cls.__mro__: __mro__ 属性返回一个包含类及其所有父类的元组,按照方法解析顺序排列。 使用 reversed 反转这个顺序,确保子类的类型信息优先。
  4. inspect.get_annotations(c): 获取每个类 c 的类型注解,返回一个字典。
  5. 类型信息合并: 遍历父类链时,将父类的类型信息合并到 params_meta 中。如果子类定义了与父类同名的参数,则子类的类型信息优先。
  6. 默认值获取: 检查类属性是否有默认值,如果有则添加到结果字典中。
  7. __getattr__ 方法: 为了模拟问题描述中“未实例化属性”的场景,重写了 __getattr__ 方法,当访问不存在的属性时抛出 AttributeError。

运行结果:

{'parent_param': {'types': [<class 'str'>]}, 'parent_default': {'types': [<class 'str'>, <class 'NoneType'>], 'default': None}, 'child_param': {'types': [<class 'str'>]}

注意事项

  • 类型覆盖: 在继承关系中,如果子类重新定义了父类的属性,并且类型注解不同,则子类的类型注解会覆盖父类的类型注解。
  • 性能: 使用反射可能会影响性能,特别是在频繁调用的场景中。 可以考虑缓存结果以提高性能。
  • 兼容性: inspect.get_annotations 是 Python 3.9 引入的,如果需要兼容更早的版本,可以使用 typing.get_type_hints。

总结

通过结合 inspect.get_annotations 和 __mro__ 属性,我们可以方便地获取类及其父类的类型注解。这对于实现一些通用的工具函数,例如自动生成 API 文档、参数校验等非常有用。 在实际应用中,需要注意类型覆盖、性能和兼容性等问题。

温馨提示: 本文最后更新于2025-06-30 22:29:27,某些文章具有时效性,若有错误或已失效,请在下方留言或联系在线客服
文章版权声明 1 本网站名称: 创客网
2 本站永久网址:https://new.ie310.com
1 本文采用非商业性使用-相同方式共享 4.0 国际许可协议[CC BY-NC-SA]进行授权
2 本站所有内容仅供参考,分享出来是为了可以给大家提供新的思路。
3 互联网转载资源会有一些其他联系方式,请大家不要盲目相信,被骗本站概不负责!
4 本网站只做项目揭秘,无法一对一教学指导,每篇文章内都含项目全套的教程讲解,请仔细阅读。
5 本站分享的所有平台仅供展示,本站不对平台真实性负责,站长建议大家自己根据项目关键词自己选择平台。
6 因为文章发布时间和您阅读文章时间存在时间差,所以有些项目红利期可能已经过了,能不能赚钱需要自己判断。
7 本网站仅做资源分享,不做任何收益保障,创业公司上收费几百上千的项目我免费分享出来的,希望大家可以认真学习。
8 本站所有资料均来自互联网公开分享,并不代表本站立场,如不慎侵犯到您的版权利益,请联系79283999@qq.com删除。

本站资料仅供学习交流使用请勿商业运营,严禁从事违法,侵权等任何非法活动,否则后果自负!
THE END
喜欢就支持一下吧
点赞11赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容