news 2026/5/9 4:49:26

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/5/8 17:51:47

计算机毕业设计springboot基于多终端的校园失物招领平台 基于SpringBoot的跨终端高校失物招领智慧平台 SpringBoot+MySQL构建的全平台校园寻物招领系统

计算机毕业设计springboot基于多终端的校园失物招领平台e125723h &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。下课铃一响&#xff0c;图书馆、食堂、操场瞬间人潮涌动&#x…

作者头像 李华
网站建设 2026/5/8 17:51:45

2025--简单点--python之状态模式

一个context有可以切换多个state&#xff0c;切换到不同的state可以做不同的handle。 该模式将与状态相关的行为抽取到独立的状态类中&#xff0c; 让原对象将工作委派给这些类的实例&#xff0c; 而不是自行进行处理。 from __future__ import annotations from abc import AB…

作者头像 李华
网站建设 2026/5/8 22:28:02

平板电脑语言设置在哪?咋添加切换?看这篇就懂

语言设置是平板电脑使用的基础。它不仅决定了屏幕上显示的文字&#xff0c;更影响了输入法、语音助手、应用商店乃至整个操作系统的交互逻辑。选对语言&#xff0c;能让设备用起来得心应手&#xff1b;设置不当&#xff0c;则可能带来持续的困扰。下面将从几个关键问题入手&…

作者头像 李华
网站建设 2026/5/9 6:14:40

JavaScript中如何监听浏览器后退按钮事件及常见问题

在Web开发中&#xff0c;处理浏览器的后退按钮行为是一个常见但容易被忽视的细节。它直接关系到单页面应用(SPA)的路由状态管理、用户操作流程的连贯性以及是否会产生意料之外的页面跳转。理解并正确监听后退事件&#xff0c;对于提升应用交互逻辑的健壮性至关重要。 如何监听浏…

作者头像 李华
网站建设 2026/5/3 10:32:33

Open WebUI图表集成快速上手指南:三步搞定数据可视化

Open WebUI图表集成快速上手指南&#xff1a;三步搞定数据可视化 【免费下载链接】open-webui Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 WebUI&#xff0c;设计用于完全离线操作&#xff0c;支持各种大型语言模型&#xff08;LLM&#xff09;运行器&#xff0c;包…

作者头像 李华
网站建设 2026/5/9 10:56:30

ServerPackCreator终极指南:从零开始构建专业级Minecraft服务器

ServerPackCreator终极指南&#xff1a;从零开始构建专业级Minecraft服务器 【免费下载链接】ServerPackCreator Create a server pack from a Minecraft Forge, NeoForge, Fabric, LegacyFabric or Quilt modpack! 项目地址: https://gitcode.com/gh_mirrors/se/ServerPackC…

作者头像 李华