news 2026/5/3 10:18:36

2025-简单点-python的元类编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2025-简单点-python的元类编程

类的类

自定义元类基础

创建一个自定义元类,通常需要继承 type并重写其 __new__或 __init__方法。

classVerboseMeta(type):"""一个在创建类时打印信息的元类示例"""def__new__(cls,name,bases,attrs):# 在类对象真正创建之前,我们可以修改属性字典 (attrs)print(f"[VerboseMeta] 正在创建类:{name}")# 例如,我们可以自动给类添加一个由元类注入的属性attrs['injected_by_meta']=f"由元类为{name}注入"# 必须调用父类的__new__方法来最终完成类的创建returnsuper().__new__(cls,name,bases,attrs)def__init__(self,name,bases,attrs):# 类对象已经创建,可以进行一些初始化后的操作print(f"[VerboseMeta] 类{name}初始化完成")super().__init__(name,bases,attrs)classMyClass(metaclass=VerboseMeta):defhello(self):return"Hello from MyClass"# 当Python解释器执行到上面的类定义时,VerboseMeta就已经开始工作了。# 输出:# [VerboseMeta] 正在创建类:MyClass# [VerboseMeta] 类 MyClass 初始化完成obj=MyClass()print(obj.hello())# 输出: Hello from MyClassprint(obj.injected_by_meta)# 输出: 由元类为MyClass注入

VerboseMeta的 __new__方法在类 MyClass被创建前被调用,
参数 name是类名(‘MyClass’),bases是基类元组(默认为空),attrs是一个包含类体内定义的所有属性(如方法、类变量)的字典
我们通过修改 attrs动态地为类添加了一个新属性 injected_by_meta

场景一:自动注册特定方法

假设我们想自

classRegisterMeta(type):def__new__(cls,name,bases,attrs):# 遍历类的属性,找出所有可调用且名字以大写字母开头的方法methods=[keyforkey,valueinattrs.items()ifcallable(value)andkey[0].isupper()]# 将这些方法名列表存入类的 'registered_methods' 属性中attrs['registered_methods']=methodsreturnsuper().__new__(cls,name,bases,attrs)classMyService(metaclass=RegisterMeta):defPublicMethod(self):# 以大写字母开头,将被注册return"This is a public method."defprivate_method(self):# 以小写字母开头,不会被注册return"This is a private method."print(MyService.registered_methods)# 输出:['PublicMethod']

元类 RegisterMeta在 MyService类创建时,扫描其属性,将符合条件的方名法记录到 registered_methods列表中,这对于构建插件系统或API框架非常有用

场景二:实现单例模式

classSingletonMeta(type):_instances={}# 用于存储每个类的唯一实例def__call__(cls,*args,**kwargs):# 当类被“调用”(实例化)时,此方法被触发ifclsnotincls._instances:# 如果该类还没有实例,则创建一个并存入字典instance=super().__call__(*args,**kwargs)cls._instances[cls]=instance# 返回字典中存储的该类的实例returncls._instances[cls]classDatabaseConnection(metaclass=SingletonMeta):def__init__(self):print("初始化数据库连接...")# 模拟耗时的连接建立# 测试db1=DatabaseConnection()# 输出:初始化数据库连接...db2=DatabaseConnection()print(db1isdb2)# 输出:True, 说明是同一个对象

关键在于元类的 __call__方法控制着类的实例化过程。通过检查实例是否已存在,我们确保了全局唯一性

进阶应用:迷你ORM框架

classField:"""描述字段的类"""def__init__(self,data_type):self.data_type=data_typeclassModelMeta(type):"""元类,用于收集Model子类的字段信息"""def__new__(cls,name,bases,attrs):# 跳过对基类Model本身的处理ifname=='Model':returnsuper().__new__(cls,name,bases,attrs)# 收集所有Field类型的属性fields={}forkey,valueinattrs.items():ifisinstance(value,Field):fields[key]=value# 将收集到的字段信息存入类的'_fields'属性中attrs['_fields']=fields# 假设表名就是类名的小写attrs['_table_name']=name.lower()returnsuper().__new__(cls,name,bases,attrs)classModel(metaclass=ModelMeta):"""所有模型类的基类"""pass# 定义具体的模型类classUser(Model):id=Field(int)name=Field(str)email=Field(str)# 使用print(User._table_name)# 输出:userprint(User._fields)# 输出:{'id': <__main__.Field object at ...>, ...}user=User()# 此时,user实例的类User已经通过ModelMeta元类,自动拥有了关于其字段和表名的元信息。

这个例子展示了元类的强大之处:它允许框架开发者(Model和ModelMeta)在后台完成繁琐的映射工作,而业务开发者(User类的定义者)只需以非常声明式的方式编写代码,就能实现复杂的功能。这正是Django ORM等框架的核心工作原理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 5:17:35

Arduino CAN库实战指南:从入门到精通CAN总线通信

Arduino CAN库实战指南&#xff1a;从入门到精通CAN总线通信 【免费下载链接】arduino-CAN An Arduino library for sending and receiving data using CAN bus. 项目地址: https://gitcode.com/gh_mirrors/ar/arduino-CAN 还在为嵌入式设备间的可靠通信而烦恼吗&#x…

作者头像 李华
网站建设 2026/5/3 7:20:35

【GESP】C++三级真题 luogu-B4414 [GESP202509 三级] 日历制作

GESP C 2025年9月三级真题&#xff0c;一维数组考点&#xff0c;难度★★☆☆☆。 luogu-B4414 [GESP202509 三级] 日历制作 题目要求 题目题解详见&#xff1a;https://www.coderli.com/gesp-3-luogu-b4414/ https://www.coderli.com/gesp-3-luogu-b4414/https://www.coder…

作者头像 李华
网站建设 2026/5/1 6:28:06

Cesium 示例集:迁徙路网特效 glsl实现

🚀 个人简介:某大型测绘遥感企业资深Webgis开发工程师,软件设计师(中级)、CSDN优质创作者 💟 作 者:柳晓黑胡椒❣️ 📝 专 栏:再识Cesium 🌈 若有帮助,还请关注 ➕ 点赞➕收藏,不行的话我再努努力💪💪💪 基于 Cesium 的迁徙路网特效 GLSL 实现 迁徙路网特效…

作者头像 李华
网站建设 2026/4/27 1:33:34

为何渴望被赞赏?过度求赞有何影响?如何建立健康评价体系?

追求他人的认可&#xff0c;本质是渴望在外部镜像中确认自我价值。这不仅是一种普遍的社会心理&#xff0c;也是许多焦虑与内耗的根源。理解“被赞赏”的驱动力&#xff0c;才能更理性地对待外界的评价&#xff0c;建立更稳固的自我内核。 为什么我们如此渴望被他人赞赏 这种渴…

作者头像 李华
网站建设 2026/4/29 22:46:06

AriaNg GUI完整指南:免费跨平台下载管理器终极解决方案

AriaNg GUI完整指南&#xff1a;免费跨平台下载管理器终极解决方案 【免费下载链接】aria-ng-gui 一个 Aria2 图形界面客户端 | An Aria2 GUI for Windows & Linux & MacOS 项目地址: https://gitcode.com/gh_mirrors/ar/aria-ng-gui AriaNg GUI是一款功能强大的…

作者头像 李华
网站建设 2026/4/28 15:28:56

macOS终极网络共享方案:HoRNDIS驱动程序完全配置指南

在移动办公日益普及的今天&#xff0c;如何将Android设备的网络快速、稳定地共享到Mac电脑上成为许多用户的迫切需求。HoRNDIS驱动程序正是解决这一痛点的专业工具&#xff0c;通过USB数据线将Android手机变身为网络设备&#xff0c;为macOS用户提供无缝的网络连接体验。 【免费…

作者头像 李华