元类的认识和基础用法

元类

“元类就是深度的魔法,99%的⽤户应该根本不必为此操⼼。
如果你想搞清楚 究竟是否需要⽤到元类,那么你就不需要它。
那些实际⽤到元类的⼈都⾮常 清楚地知道他们需要做什么,⽽且根本不需要解释为什么要⽤元类。“——蒂姆·彼得斯TimPeters

什么是元类

在python中,所有的类,都是基于元类创建的。

class demo(object):pass

在python中,一切都是对象,类也是对象,所以一个类必定会有一个类型。

此处的object是所有python类层次结构的基类,也就是说所有的类都是继承它的。

那么,object又是什么类型?

print(type(object))

我们打印出来看一下:

<class 'type'>

显示的就是元类。

我们回到前面说的那句话,再加上注解会更容易理解了。

  • 在python中,一切都是对象(object),类(class)也是对象(object),所以一个类(class)必定会有一个类型(type)。
  • 用来创建类的类,叫做元类,函数type实际上也是一个元类。
  • python中任何形式类以及python3中的任何类都是type元类的一个实例。

需要注意的是,我们要区分元类和继承的基类:

  • type:是元类,所有的类都是通过type所创建出来的
  • object:顶层的基类,所有类的继承顶层父类都是object
  • type是创造者女娲,object是女娲创造的第一个孩子。(不是很准确,但这样好理解)

参数详解

type源码

class type(object):"""type(object_or_name, bases, dict)type(object) -> the object's typetype(name, bases, dict) -> a new type"""

源码中写道,使用type(name, bases, dict)就可以定义一个新的元类。

参数详解

  • name : 表示要创建的类的名称。(字符串类型)

  • bases : 继承类的基类元组(或包含基类的元类)。(元组类型)

  • dict : 类属性和方法。(字典类型)

自定义类与元类创建的比对

我们自己创建类,代码如下

class MyClass(object):x = 42obj = MyClass()
print(obj.x) # 输出42

这里,类名为MyClass,继承了基类object,属性为x=42

那么我们就按照元类创建类的方式构造一个和如上类一样功能的类。

MyClass = type('MyClass',(object,),{"x":42})
obj = MyClass()
print(obj.x) #输出42

由于object是默认继承的基类,bases参数可以为空,代码如下:

MyClass = type('MyClass',(),{"x":42})
obj = MyClass()
print(obj.x) #输出42

既然我们可以自己创建类,为什么要用元类?

别问,问就回去文章开头TimPeters说的那句话。

深入一下

经过上面的例子我们知道了,object是所有类的基类,而type是创建类的类,那么我如果把基类修改了,是不是创建出来的类就是自动继承了我所修改后的基类?

定义一个元类

  • 声明一个类,并继承自type类。
  • 在元类中定义__new__方法,该方法用于创建新的类。
  • __new__方法中可以自定义类的行为、属性和方法。
class MyMeta(type):def __new__(meta, name, bases, attrs):# 自定义类的行为print("想不到吧,我才是基类")# 创建并返回新的类return super().__new__(meta, name, bases, attrs)

使用元类动态创建类

在创建类时,可以使用metaclass参数指定所使用的元类。

声明一个普通的类,并将metaclass参数设置为定义的元类,metaclass默认为type

class MyClass(metaclass=MyMeta):# 类的定义hh = 123print("呜呜呜,我就是一个普通的类,可我的元类不是type了,而是自定义的")

运行以上代码:

aa = MyClass()
print(aa.hh)
#输出结果如下>>>
呜呜呜,我就是一个普通的类,可我的元类不是type了,而是自定义的
想不到吧,我才是基类
123

如果我们没有指定元类为自定义的元类,输出将会没有想不到吧那一行。

class MyClass2():# 类的定义h = 123print("呜呜呜,我就是一个普通的类,可我的元类不是type了,而是自定义的")aa = MyClass2()
print(aa.h)
#输出结果如下>>>
呜呜呜,我就是一个普通的类,可我的元类不是type了,而是自定义的
123

用元类写一个简单的日志记录器

class LogMeta(type):def __new__(meta, name, bases, attrs):# 检查属性中的日志消息logs = {}for key, value in attrs.items():if isinstance(value, str) and value.startswith("LOG "):logs[key] = value# 添加日志方法for key in logs.keys():def log_func(self, message):print(f"Log {key}: {message}")attrs[key] = log_func# 创建并返回新的类return super().__new__(meta, name, bases, attrs)class MyLogger(metaclass=LogMeta):LOG_INFO = "LOG INFO"LOG_ERROR = "LOG ERROR"LOG_WARNING = "LOG WARNING"

在上面的示例中,我们创建了一个LogMeta元类,它通过检查类属性中的日志消息并动态创建日志方法。然后我们使用LogMeta元类创建了一个MyLogger类,并在其中定义了几个日志消息。最后,我们可以使用MyLogger类创建对象并调用日志方法。

logger = MyLogger()
logger.LOG_INFO("This is an informational message.")
logger.LOG_ERROR("An error occurred.")

当我们运行上面的代码时,它将输出以下内容:

Log LOG_WARNING: This is an informational message.
Log LOG_WARNING: An error occurred.

下一节我们讲讲如何将它运用在我们的测试框架里面动态创建测试用例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/16121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL数据库中,查询时提示表不存在的解决办法

最近遇到一个奇怪的问题&#xff0c;以前从来没有遇到过&#xff0c;在postgres SCHEMA下执行select * from table1语句时&#xff0c;提示表不存在&#xff0c;而实际这个表确是存在的&#xff0c;只不过是在public SCHEMA下。在public SCHEMA下执行这个sql语句是没有问题的。…

【Linux下6818开发板(ARM)】在液晶屏上显示RGB颜色和BMP图片

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

C++ 类和对象

面向过程/面向对象 C语言是面向过程&#xff0c;关注过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题 C是基于面对对象的&#xff0c;关注的是对象——将一件事拆分成不同的对象&#xff0c;依靠对象之间的交互完成 引入 C语言中结构体只能定义…

flask处理表单数据

flask处理表单数据 处理表单数据在任何 web 应用开发中都是一个常见的需求。在 Flask 中&#xff0c;你可以使用 request 对象来获取通过 HTTP 请求发送的数据。对于 POST 请求&#xff0c;可以通过 request.form 访问表单数据。例如&#xff1a; from flask import Flask, r…

IDEA中连接虚拟机 管理Docker

IDEA中连接虚拟机 管理Docker &#x1f4d4; 千寻简笔记介绍 千寻简笔记已开源&#xff0c;Gitee与GitHub搜索chihiro-notes&#xff0c;包含笔记源文件.md&#xff0c;以及PDF版本方便阅读&#xff0c;且是用了精美主题&#xff0c;阅读体验更佳&#xff0c;如果文章对你有帮…

【点云处理教程】00计算机视觉的Open3D简介

一、说明 Open3D 是一个开源库&#xff0c;使开发人员能够处理 3D 数据。它提供了一组用于 3D 数据处理、可视化和机器学习任务的工具。该库支持各种数据格式&#xff0c;例如 .ply、.obj、.stl 和 .xyz&#xff0c;并允许用户创建自定义数据结构并在程序中访问它们。 Open3D 广…

KafKa脚本操作

所有操作位于/usr/local/kafka_2.12-3.5.1/bin。 rootubuntu2203:/usr/local/kafka_2.12-3.5.1/bin# pwd /usr/local/kafka_2.12-3.5.1/bin rootubuntu2203:/usr/local/kafka_2.12-3.5.1/bin# ls connect-distributed.sh kafka-delegation-tokens.sh kafka-mirror-mak…

15. Spring AOP 的实现原理 代理模式

目录 1. 代理模式 2. 静态代理 3. 动态代理 3.1 JDK 动态代理 3.2 CGLIB 动态代理 4. JDK 动态代理和 CGLIB 动态代理对比 5. Spring代理选择 6. Spring AOP 实现原理 6.1 织入 7. JDK 动态代理实现 8. CGLIB 动态代理实现 9. 总结 1. 代理模式 代理模式&#xf…

Mac查看系统状态

syatem profiler mac系统中提供了system profiler来查看系统的详细信息&#xff0c;包括硬件、网络以及安装的软件 Console 显示了系统上的日志文件信息&#xff0c;有助于诊断问题 Activity Monitor 可以提供正在运行的系统的相关信息 https://zhhll.icu/2021/Mac/查看系统…

【云原生】一文学会Docker存储所有特性

目录 1.Volumes 1.Volumes使用场景 2.持久将资源存放 3. 只读挂载 2.Bind mount Bind mounts使用场景 3.tmpfs mounts使用场景 4.Bind mounts和Volumes行为上的差异 5.docker file将存储内置到镜像中 6.volumes管理 1.查看存储卷 2.删除存储卷 3.查看存储卷的详细信息…

Java课题笔记~Maven基础

2、Maven 基础 2.1 Maven安装与配置 下载安装 配置&#xff1a;修改安装目录/conf/settings.xml 本地仓库&#xff1a;存放的是下载的jar包 中央仓库&#xff1a;要从哪个网站去下载jar包 - 阿里云的仓库 2.2 创建Maven项目

丁鹿学堂:前端学习进阶指南之react入门(react在html中使用数据绑定和修改)

在html中使用react 今天跟大家分享react的基础语法。 我们采用最简单的方法&#xff0c;就是在html中引入react 因为一上来就使用脚手架的话&#xff0c;很多配置大家不一定清楚。 而在html中使用react的话&#xff0c;可以直接去学习react最基本的语法。 这是零基础学习r…

MySQL数据库 【索引事务】

目录 一、概念 二、索引的优缺点 1、索引的优点 2、索引的缺陷 三、索引的使用 1、查看索引 2、创建索引 3、删除索引 四、索引底层的数据结构 1、B树 2、B树 五、索引事务 1、概念和回滚 2、事务的使用 3、事务的基本特性 4、并发会遇到的问题 &#xff08…

jenkins执行jmeter时,报Begin size 1 is not equal to fixed size 5

jenkins执行jmeter脚本的时候一直提示如下错误&#xff1a; Tidying up ... Fri Jul 28 17:03:53 CST 2023 (1690535033178) Error generating the report: org.apache.jmeter.report.dashboard.GenerationException: Error while processing samples: Consumer failed wi…

游游的排列构造

示例1 输入 5 2 输出 3 1 5 2 4 示例2 输入 5 3 输出 2 1 4 3 5 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N1e55; int n,k; int main(){scanf("%d%d",&n,&k);int xn-k1;int yn-k;int f1;for(int i1;i&l…

LLVM框架系统

Getting Started with LLVM Core Libraries 参考1 LLVM是构架编译器(compiler)的框架系统&#xff0c;以C编写而成&#xff0c;用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time)&#xff0c;对开…

P1162 填涂颜色

题目描述 由数字 0 组成的方阵中&#xff0c;有一任意形状闭合圈&#xff0c;闭合圈由数字 1 构成&#xff0c;围圈时只走上下左右 4 个方向。现要求把闭合圈内的所有空间都填写成 2。例如&#xff1a;66 的方阵&#xff08;n6&#xff09;&#xff0c;涂色前和涂色后的方阵如…

产品经理如何平衡用户体验与商业价值?

近期负责前端产品设计工作的小李忍不住抱怨&#xff1a;公司总是要求客户第一&#xff0c;实现客户良好体验&#xff0c;但在实际操作过程中&#xff0c;面向用户 体验提升的需求&#xff0c;研发资源计划几乎很难排上&#xff0c;资源都放在公司根据业务价值排序的需求…

大家做性能测试都用什么工具

在进行测试时&#xff0c;选择适合的测试工具至关重要&#xff0c;因为优秀的测试工具能够显著提高工作效率。对于性能测试和自动化测试而言&#xff0c;大多数人会选择传统的JMeter等工具&#xff0c;然而这些工具存在学习成本高、使用门槛高的问题。 因此&#xff0c;我在这…

intellij 编辑器内性能提示

介绍 IntelliJ IDEA已经出了最新版的2023.2&#xff0c;最耀眼的功能无法两个 AI Assistant编辑器内性能提示 AI Assistant 已经尝试过了是限定功能&#xff0c;因为是基于open ai,所以限定的意思是国内无法使用&#xff0c;今天我们主要介绍是编辑器内性能提示 IntelliJ Pr…