当前位置: 首页 > 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; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...