当前位置: 首页 > news >正文

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等框架的核心工作原理。

http://www.jsqmd.com/news/104672/

相关文章:

  • 39、Linux 时间控制与定时器机制详解
  • 老尹家 联系方式: 正规渠道识别方法及联系使用实用建议 - 十大品牌推荐
  • SAP-MR21和MR22的应用
  • 中山豪车维修服务推荐指南:场景适配与高性价比之选 - 优质品牌商家
  • 计算机毕业设计springboot基于多终端的校园失物招领平台 基于SpringBoot的跨终端高校失物招领智慧平台 SpringBoot+MySQL构建的全平台校园寻物招领系统
  • Cadence17.4 通孔类焊盘制作
  • 2025中山豪车钣金喷漆优质机构推荐指南:汽车维修钣金喷漆、汽车维修附件、空调不制冷汽车维修、豪华汽车维修、24小时市道路救援 - 优质品牌商家
  • 实验室气路系统场景化推荐指南:解决空间纯度与连续供气痛点 - 优质品牌商家
  • 2025--简单点--python之状态模式
  • 2025实验室气路施工品牌核心维度评测报告:实验室气路设计、实验室气路设计规范、科研院所实验室气路、高校实验室气路、实验室气路安装 - 优质品牌商家
  • 髋关节翻修double switch手术,你了解多少?
  • OpenWrt网络加速神器:TurboACC让你的路由器性能翻倍
  • Taiga 终极指南:免费开源项目管理工具的完整应用方案
  • 基于Gradle8.0的插件开发
  • 使用pe修改电脑密码的办法
  • EmotiVoice与RVC结合使用指南:实现更精细的声音定制
  • ASMR音频高效获取终极指南:一键下载asmr.one海量内容
  • Obsidian Tasks插件:让知识库变身高效任务管理中心的终极指南
  • Windows XP系统启动出现登录对话框的原因及解决办法
  • 大模型应用开发实战:从RAG踩坑到智能体优化,一篇搞定智能问答系统!
  • 基于Vue3和Element Plus构建现代化后台管理系统架构实践
  • Java如何通过JNI实现调用C/C++代码,你知道吗?
  • 开题报告新手工具:9大AI+步骤指南排名
  • Cesium 示例集:迁徙路网特效 glsl实现
  • Label Studio多语言配置终极指南:三步完成界面本地化
  • C4droid支持OpenGL,功能与限制你得知道
  • 平板电脑语言设置在哪?咋添加切换?看这篇就懂
  • 开源敏捷协作平台完整教程:提升团队效率的终极指南
  • ExoPlayer实时流媒体播放:从入门到精通的完整指南
  • Python中append()方法的使用、原理及效率解析