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

27. 元类

一、什么是元类

  在 Python 中,一切皆为对象,即类也是一个对象。type 是内置的元类。我们用 class 关键字定义的所有的类以及内置的类都是由元类 type(内置的元类) 实例化产生的。

class Person:def __init__(self, name, age):self.name = nameself.age = agedef show_info(self):print(f"name: {self.name}, age: {self.age}")print(type(Person))
print(type(int))

当 Python 解释器遇到 class 的时候,实际上会进行调用,其目的是:至少要知道有哪些属性,有哪些方法,然后将这些类属性、方法传递到元类 type 中,进行创建一个对象,这个对象就是我们所谓的类对象。

二、class机制分析

# 1、类名
class_name = "Person"
# 2、类的基类
class_base = (object,)
# 3、执行类体代码拿到类的名称空间
class_dict = {"name": "unknown"}
class_body = """
def __init__(self, name, age):self.name = nameself.age = agedef show_info(self):print(f"name: {self.name}, age: {self.age}")
"""exec(class_body, {}, class_dict)
print(class_dict)# 4、调用元类
Person = type(class_name, class_base, class_dict)
print(Person)# 5、创建对象
p = Person("Sakura", 10)
p.show_info()
# 1、类名
class_name = "Person"
# 2、类的基类
class_base = (object,)
# 3、执行类体代码拿到类的名称空间
def show_info(self):print(f"name: {self.name}")@classmethod
def description(cls):print(f"{cls.name}是一个人")@staticmethod
def static():print("我是一个静态方法")class_dict = {"name": "unknown", "show_info": show_info, "description": description, "static": static}# 4、调用元类
Person = type(class_name, class_base, class_dict)
print(Person)# 5、创建对象
p = Person()
p.show_info()
p.description()
p.static()

三、自定义元类

# 只有继承了type类的类才是元类
class MyMeta(type):# cls当前所在的类,*args、**kwargs调用类时所传入的参数def __new__(cls,*args,**kwargs):print("__new__()方法运行了")print(cls)print(args)print(kwargs)return type.__new__(cls, *args, **kwargs)# __init__()接收的参数是__new__()方法返回的def __init__(self, class_name, class_bases, class_dict):print("__init__()方法运行了")print(self)print(class_name)print(class_bases)print(class_dict)def __call__(self,*args,**kwargs):print(self)print(args)print(kwargs)# MyMeta.__call__()方法会先调用Person类内的__new__()方法obj = self.__new__(self)# MyMeta.__call__()方法内会调用Person类内的__init__()方法self.__init__(obj,*args,**kwargs)# MyMeta.__call__()方法会返回一个初始化好的对象return obj"""
调用MyMeta发生的三件事:1、先造一个空对象,调用类内的__new__()方法,就是调用type.__call__()方法2、调用MyMeta这个类内的__init__()方法,完成初始化对象的操作3、返回初始化好的对象
Person = MyMeta(class_name,class_bases,class_dict)
""""""
类的产生:Person = MyMeta() --> type.__call__()干的三件事:1、type.__call__()方法内会先调用MyMeta类内的__new__()方法2、type.__call__()方法内会调用MyMeta类内的__init__()方法3、type.__call__()方法会返回一个初始化好的对象
"""
class Person(metaclass=MyMeta):def __new__(cls,*args,**kwargs):# 产生真正的对象return object.__new__(cls)def __init__(self,name,age):self.name = nameself.age = agedef show_info(self):print(f"name: {self.name}, age: {self.age}")"""
类的调用:p = Person("Sakura",10) --> MyMeta.__call__()干的三件是1、MyMeta.__call__()方法内会先调用Person类内的__new__()方法2、MyMeta.__call__()方法内会调用Person类内的__init__()方法3、MyMeta.__call__()方法会返回一个初始化好的对象
"""
p = Person("Sakura",10)
print(p)
print(p.__dict__)
# 只有继承了type类的类才是元类
class MyMeta(type):def __new__(cls, class_name, class_base, class_dict):print("__new__()方法运行了")# 方法1:通过type来做类对象的创建return type(class_name, class_base, class_dict)# 方法2:复用type.__init__()方法#return type.__new__(cls, class_name, class_base, class_dict)class Person(metaclass=MyMeta):def __init__(self,name,age):self.name = nameself.age = agedef show_info(self):print(f"name: {self.name}, age: {self.age}")p = Person("Sakura",10)
print(p)
print(p.__dict__)

只要调类,那么会依次调用类内的 __new__() 方法,在调用 __init__() 方法;

如果想要一个对象可以加括号调用,需要在该对象的类中添加一个 __call__() 方法;

四、利用元类实现单例模式

class MyType(type):def __init__(self, name, base, attrs):super().__init__(name, base, attrs)self.instance = Nonedef __call__(self, *args, **kwargs):# 判断是否有对象,有,则不创建,没有,则创建if not self.instance:# 调用自己的那个类的__new__()创建对象self.instance = self.__new__(self)# 调用自己的那个类的__init__()初始化对象self.__init__(self.instance, *args, **kwargs)return self.instanceclass P(metaclass=MyType):passp1 = P()
print(p1)p2 = P()
print(p1)

相关文章:

27. 元类

一、什么是元类 在 Python 中,一切皆为对象,即类也是一个对象。type 是内置的元类。我们用 class 关键字定义的所有的类以及内置的类都是由元类 type(内置的元类) 实例化产生的。 class Person:def __init__(self, name, age):se…...

PHP木马编写

一、最简单的一句话木马 <?php eval($_REQUEST[cmd]); ?> 1. <?php 和 ?> <?php 和 ?> 是 PHP 代码的开始和结束标记&#xff0c;表示 PHP 代码块的范围。 2. eval() eval() 是 PHP 中的一个内建函数&#xff0c;用来执行字符串类型的 PHP 代码。…...

游戏AI实现-寻路算法(Dijkstra)

戴克斯特拉算法&#xff08;英语&#xff1a;Dijkstras algorithm&#xff09;&#xff0c;又称迪杰斯特拉算法、Dijkstra算法&#xff0c;是由荷兰计算机科学家艾兹赫尔戴克斯特拉在1956年发现的算法。 算法过程&#xff1a; 1.首先设置开始节点的成本值为0&#xff0c;并将…...

Android OpenGLES2.0开发(九):图片滤镜

“当你改变想法的时候&#xff0c;记得也要改变你的世界。”——诺曼文森特皮尔 Android OpenGLES开发&#xff1a;EGL环境搭建Android OpenGLES2.0开发&#xff08;一&#xff09;&#xff1a;艰难的开始Android OpenGLES2.0开发&#xff08;二&#xff09;&#xff1a;环境搭…...

SQLite Update 语句

SQLite Update 语句 SQLite 的 UPDATE 语句用于更新数据库表中的现有记录。使用 UPDATE 语句&#xff0c;您可以修改一个或多个列的值。本教程将详细介绍如何使用 SQLite UPDATE 语句&#xff0c;包括语法、示例以及一些最佳实践。 语法 SQLite UPDATE 语句的基本语法如下&a…...

Metaploit-永恒之蓝漏洞利用

1&#xff1a;Metaploit介绍   本次测试主要是利用永恒之蓝漏洞对windows7进行控制利用&#xff0c;掌握Metaploit工具的使用&#xff0c;知道永恒之蓝的漏洞利用原理。永恒之蓝是在Windows的SMB服务处理SMB v1请求时发生的漏洞&#xff0c;这个漏洞导致攻击者在目标系统上可…...

机器学习预处理-表格数据的空值处理

机器学习预处理-表格数据的空值处理 机器学习预处理-表格数据的分析与可视化中详细介绍了表格数据的python可视化&#xff0c;可视化能够帮助我们了解数据的构成和分布&#xff0c;是我们进行机器学习的必备步骤。上文中也提及&#xff0c;原始的数据存在部分的缺失&#xff0…...

数据结构_平衡二叉树

结点类 构造函数分为有参和无参&#xff0c;相同点都是初始化树高为1 class Node { public:int data; // 用于输出int val; // 数据域&#xff0c;用于排序int height; // 树高Node* left;Node* right;Node();Node(int v, int d);static int max(int a, int b); };Node::N…...

C++对象的赋值与复制复制构造函数(指针数据成员)

一、对象的赋值 同类对象之间可以相互赋值&#xff0c;对象赋值的一般形式&#xff1a;对象名2 对象名1; 原理是&#xff0c;赋值运算符的重载。仅赋值&#xff0c;因此赋值前&#xff0c;需要先定义并初始化对象2。 对象的赋值针对指对象中所有数据成员的值&#xff1b; 对…...

Coding Caprice - monotonic stack2

42. 接雨水 class Solution { public:int trap(vector<int>& height) {stack<int> sh;int out 0;for(int i0; i<height.size(); i){while(!sh.empty() && height[sh.top()]<height[i]){int bo height[sh.top()];sh.pop();if(sh.empty()){brea…...

Spring Mvc面试题(常见)

1 Spring MVC的执行流程 用户发起请求,请求先被Servlet拦截以后,转发给SpringMVC框架SpringMVC 里面的DispatcherServlet(核心控制器) 接收到请求,并转发给HandlerMappingHandlerMapping负责解析请求,根据请求信息和配置信息找到匹配的Controller类(当这里有配置拦截器,会…...

opencv # Sobel算子、Laplacian算子、Canny边缘检测、findContours、drawContours绘制轮廓、外接矩形

一、Sobel算子 案例图片 cv2.Sobel(src, ddepth, dx, dy, ksize3, scale1, delta0, borderTypeNone) 功能&#xff1a;用于计算图像梯度&#xff08;gradient&#xff09;的函数 参数&#xff1a; src: 输入图像&#xff0c;它应该是灰度图像。 ddepth: 输出图像的所需深度&am…...

Neo4j插入数据逐级提升速度4倍又4倍

语雀版&#xff1a;https://www.yuque.com/xw76/back/dtukgqfkfwg1d6yo 目录 背景介绍初始方案Node()创建事务批量提交记录Node是否存在生成Cypher语句执行数据库参数优化切换成85k个三元组测试建索引&#xff08;很显著&#xff01;&#xff01;&#xff01;&#xff09;MATCH…...

C++特殊类设计(单例模式等)

目录 引言 1.请设计一个类&#xff0c;不能被拷贝 2. 请设计一个类&#xff0c;只能在堆上创建对象 为什么设置实例的方法为静态成员呢 3. 请设计一个类&#xff0c;只能在栈上创建对象 4. 请设计一个类&#xff0c;不能被继承 5. 请设计一个类&#xff0c;只能创建一个对…...

J8学习打卡笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 Inception v1算法实战与解析 导入数据数据预处理划分数据集搭建模型训练模型正式训练结果可视化详细网络结构图个人总结 import os, PIL, random, pathlib imp…...

前端学习-操作元素内容(二十二)

目录 前言 目标 对象.innerText 属性 对象.innerHTML属性 案例 年会抽奖 需求 方法一 方法二 总结 前言 曾经沧海难为水&#xff0c;除却巫山不是云。 目标 能够修改元素的文本更换内容 DOM对象都是根据标签生成的,所以操作标签,本质上就是操作DOM对象&#xff0c;…...

【踩坑】pip离线+在线在虚拟环境中安装指定版本cudnn攻略

pip离线在线在虚拟环境中安装指定版本cudnn攻略 在线安装离线安装Windows环境&#xff1a;Linux环境&#xff1a; 清华源官方帮助文档 https://mirrors.tuna.tsinghua.edu.cn/help/pypi/ 标题的离线的意思是先下载whl文件再安装到虚拟环境&#xff0c;在线的意思是直接在当前虚…...

golang操作sqlite3加速本地结构化数据查询

目录 摘要Sqlite3SQLite 命令SQLite 语法SQLite 数据类型列亲和类型——优先选择机制 SQLite 创建数据库SQLite 附加数据库SQLite 分离数据库 SQLite 创建表SQLite 删除表 SQLite Insert 语句SQLite Select 语句SQLite 运算符SQLite 算术运算符SQLite 比较运算符SQLite 逻辑运算…...

vllm加速(以Qwen2.5-7B-instruction为例)与流式响应

1. vllm介绍 什么是vllm? vLLM 是一个高性能的大型语言模型推理引擎&#xff0c;采用创新的内存管理和执行架构&#xff0c;显著提升了大模型推理的速度和效率。它支持高度并发的请求处理&#xff0c;能够同时服务数千名用户&#xff0c;并且兼容多种深度学习框架&#xff0c;…...

WordPress弹窗公告插件-ts小陈

使用效果 使用后网站所有页面弹出窗口 插件特色功能 设置弹窗公告样式&#xff1a;这款插件可展示弹窗样式公告&#xff0c;用户点击完之后不再弹出&#xff0c;不会频繁打扰用户。可设置弹窗中间的logo图&#xff1a;这款插件针对公告图片进行独立设置&#xff0c;你可以在设…...

人事档案整理系统开发记录

档案整理系统开发记录 本篇文章&#xff0c;用于记录我个人开发档案整理工具的所有问题。 说明&#xff1a;开发该工具适用于人事档案处理工具&#xff0c;适用于档案处理&#xff0c;帮助档案整理人员更轻松的移交。 我会一步一步记录&#xff0c;整个软件开的所有的问题&…...

从PubMed到知识库:手把手教你用Python把医学文献数据存进MySQL/CSV(含完整代码)

从PubMed到知识库&#xff1a;构建医学文献智能管理系统的Python实战指南 在生物医学研究领域&#xff0c;每天都有数以万计的新文献涌入PubMed数据库。面对如此庞大的知识海洋&#xff0c;研究人员常常陷入两难&#xff1a;如何高效获取目标文献&#xff1f;更重要的是&#x…...

STM32串口发送字符串的底层机制与优化实践

1. STM32串口发送字符串的底层机制解析在嵌入式开发中&#xff0c;USART&#xff08;通用同步异步收发传输器&#xff09;是最常用的外设之一。当我们需要通过串口发送字符串时&#xff0c;实际上是将数据写入发送数据寄存器&#xff08;TDR&#xff09;&#xff0c;然后由硬件…...

【全球首批C++27静态反射商用项目解密】:西门子PLC配置引擎重构实测——编译时间+12%,运行时内存下降93.7%

第一章&#xff1a;C27静态反射工业应用案例C27引入的静态反射&#xff08;Static Reflection&#xff09;核心特性——基于std::reflexpr与编译期元对象模型&#xff08;Meta Object Model, MOM&#xff09;——已进入关键工业验证阶段。多家汽车电子与工业控制厂商在AUTOSAR …...

2025届学术党必备的降重复率网站横评

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 研究人工智能开题报告的工具&#xff0c;借助自然语言处理技术&#xff0c;靠着学术大数据分…...

ExtendedChars:Adafruit GFX的UTF-8扩展字符支持方案

1. 项目概述 ExtendedChars 是一个专为 Adafruit GFX 图形库设计的轻量级扩展组件&#xff0c;其核心工程目标是突破原生 GFX 库对 ASCII 字符集&#xff08;0x00–0x7F&#xff09;的硬性限制&#xff0c;实现对 UTF-8 编码多字节字符的可靠解析与渲染。该库并非重写显示驱动…...

FC-CLIP实战:为什么说“卷积不死”?在开放词汇分割中冻结CLIP主干的深度解析与避坑指南

FC-CLIP技术解析&#xff1a;卷积架构在开放词汇分割中的不可替代性 当整个计算机视觉领域似乎都被Transformer架构席卷时&#xff0c;FC-CLIP论文却掷地有声地宣告"卷积不死"。这个看似反潮流的结论背后&#xff0c;隐藏着哪些被忽视的视觉归纳偏置&#xff1f;冻结…...

从85分到95+:复盘我在科大奥锐虚拟仿真实验平台踩过的那些‘坑’

从85分到95&#xff1a;科大奥锐虚拟仿真实验平台的实战避坑指南 第一次接触科大奥锐虚拟仿真实验平台时&#xff0c;我和大多数同学一样&#xff0c;以为这不过是传统实验的电子版。直到连续三次实验分数卡在85分上下&#xff0c;才意识到这个平台对操作细节的严苛程度远超预期…...

CDA Level-2 考试全攻略:从报名到备考的保姆级教程(含最新题库资源)

CDA Level-2 考试全攻略&#xff1a;从报名到备考的保姆级教程 最近两年数据分析师认证热度持续攀升&#xff0c;CDA认证作为国内认可度较高的专业证书之一&#xff0c;Level-2考试通过率常年维持在40%左右。不同于Level-1的基础考核&#xff0c;Level-2更注重实际分析能力与统…...

告别手输!用Shell脚本自动化你的GROMACS伞形采样全流程(附赠配置文件)

告别手输&#xff01;用Shell脚本自动化你的GROMACS伞形采样全流程&#xff08;附赠配置文件&#xff09; 在计算化学领域&#xff0c;GROMACS作为分子动力学模拟的利器&#xff0c;其强大的功能背后往往伴随着繁琐的命令行操作。特别是进行伞形采样&#xff08;Umbrella Sampl…...