python高级之元类

news2024/11/24 15:25:47

在这里插入图片描述


python高级之元类

  • 一、Type创建类
    • 1、传统方式创建类
    • 2、非传统方式
  • 二、元类
  • 三、总结

一、Type创建类

class A(object):

    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        data = object.__new__(cls)
        return data

根据类创建对象
obj=A(‘kobe’)
1、执行类的new方法,创建对象(空对象),【构造方法】 {}
2、执行类的init方法,初始化对象 ,【初始化方法】 {‘name’:‘kobe’}

对象是基于类创建出来的;问题:类是由谁创建的?
类默认是由type创建的

1、传统方式创建类

class A(object):
    v1 = 123

    def func(self):
        return 666


print(A)			#<class '__main__.A'>

2、非传统方式

类名
继承类
成员

A1 = type('A', (object,), {"v1": 123, "func": lambda self: 666})
print(A1)        #<class '__main__.A'>

# 根据类创建对象
obj1 = A1()			#<__main__.A object at 0x0000017049D035E0>
print(obj1)


# 调用对象中的func方法 
print(obj1.func())  #666

类默认由type创建,怎么让一个类的创建改为其他的东西呢? 元类。

二、元类

元类:指定类由谁来创建

1、Foo类由MyType创建,代码如下

class MyType(type):
    pass


# Foo类由MyType创建
class Foo(object, metaclass=MyType):
    pass

2、假设Foo是一个对象,它是由MyType类创建。

class MyType(type):

    def __init__(self, *args, **kwargs):
        print('init')
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类
        print('new')
        new_cls = super().__new__(cls, *args, **kwargs)
        print(new_cls)
        return new_cls


# 假设Foo是一个对象,由MyType类创建。
class Foo(object, metaclass=MyType):
    pass

执行结果

new
<class '__main__.Foo'>
init

3、类加括号得到的是对象,执行的是__init__()和__new__()方法,对象加括号执行__call__()方法

class F1(object):
    def __init__(self):
        print('init')

    # def __new__(cls, *args, **kwargs):
    #     print('new')

    def __call__(self, *args, **kwargs):
        print(111)


# 类加括号得到的是对象,执行的是__init__和__new__方法
obj = F1()

# 对象加括号执行call方法
obj()

执行结果

init
111

4、假设Foo是一个对象,由MyType创建。
Foo类其实是MyType的一个对象。
Foo() 加括号执行的是——》MyType类中的__call__()方法

__call__()方法实现的功能是:
1、调用自己那个类的__new__方法创建对象
empty_object=self.__new__(self)
2、调用你自己那个类__init__方法去初始化对象
self.__init__(empty_object,*args,**kwargs)
3、将创建的对象返回:return empty_object

class MyType(type):

    def __init__(self, *args, **kwargs):
        print('init')
        super().__init__(*args, **kwargs)

    def __new__(cls, *args, **kwargs):
        # 创建类
        print('new')
        new_cls = super().__new__(cls, *args, **kwargs)
        print(new_cls)
        return new_cls

    def __call__(self, *args, **kwargs):
        # 1、调用自己哪个类的__new__方法创建对象
        empty_object=self.__new__(self)
        #2、调用你自己那个类 __init__方法去初始化
        self.__init__(empty_object,*args,**kwargs)

        return empty_object


# 假设Foo是一个对象,由MyType创建。
#  Foo类其实是MyType的一个对象。
# Foo()  ——》MyType对象()
class Foo(object, metaclass=MyType):

    def __init__(self,name):
        self.name=name

v1=Foo('666')

print(v1)
print(v1.name)

三、总结

1、当我们不写MyType类时,Type中已经帮我们定义好了
__init__
__new__
__call__ 方法了
当我定义了MyType类时,
__init__
__new__
__call__ 方法是我们自己定义的

2、这就是为什么实例化对象的时候,先去创建对象再去初始化对象,Type类中已经实现了先 __new__()__init__()

在这里插入图片描述
3、代码从上到下执行,当执行到class Foo(object, metaclass=MyType)
先创建这个类,去MyType中的__new__()创建方法
__init__()实例化方法,类在内存中创建好了,
但是MyType中的__call__()方法是不执行的,因为类后面没有加括号
如果类后面加了括号Foo(),会执行MyType的__call__()方法

在这里插入图片描述
4、如果自己定义的类中实现了__call__方法,此时是不会执行的,因为Foo是MyType创建出来的

在这里插入图片描述
5、如果要执行Foo类的__call__方法,需要实例化Foo类的对象v1,
然后v1加括号
在这里插入图片描述


在这里插入图片描述

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

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

相关文章

前端处理接口直接返回的图片

有时候接口会直接返回图片而不是连接&#xff0c;前端需要处理后才能使用。 首先你可能需要设置responseType: blob’处理响应数据格式。 直接使用 将接口及参数动态拼接成img.src直接使用 <img src"http://test.com/api/img?size50x50" alt"">i…

Spring Webflux 详解

目录 0、组件对比 1、WebFlux 1、引入 2、Reactor Core 1、HttpHandler、HttpServer 3、DispatcherHandler 1、请求处理流程 4、注解开发 1、目标方法传参 2.返回值写法 5、文件上传 6、错误处理 7、RequestContext 8、自定义Flux配置 9、Filter WebFlux&am…

python并发编程:阻塞IO

阻塞IO&#xff08;blocking IO&#xff09; 在Linux中&#xff0c;默认情况下所有的socket都是blocking&#xff0c;一个典型的读操作流程大概是这样&#xff1a; 当用户进程调用了recvfrom这个系统调用&#xff0c;kernel就开始了IO的第一个阶段&#xff1a;准备数据。对于…

将Remix和本地文件连接

Remix连接本地文件 推荐使用网页版本的Remix&#xff0c;因为它是实时更新的&#xff0c;还可以连接MetaMask直接进行使用。 打开remix网页&#xff0c;可以通过 create a new workspace新建页面 然后找到我们要连接 的文件目录&#xff0c;在该目录中打开终端&#xff0c;如…

Pytorch学习 day05(RandomCrop、Transforms工具使用总结)

RandomCrop 将PIL或Tensor格式的输入图片&#xff0c;随机裁剪指定尺寸的部分输入尺寸可以为序列或单个整形数字代码如下&#xff1a; from PIL import Image from torchvision import transforms from torch.utils.tensorboard import SummaryWriterimg Image.open("i…

通过hyperbeam创建梁单元截面属性

1、为模型中标准的圆柱形创建梁单元和赋予属性&#xff1b; 2、为模型中不标准的对称性实体创建梁单元和赋予属性&#xff1b; 3、为模型中壳体部分创建梁单元和赋予属性&#xff1b;

C++进阶之路---继承(一)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、继承的概念及定义 1.继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0…

MybatisPlus入门详解

一、MyBatisPlus 简介 1.1 创建新模块 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency> 由于mp并未被收录到idea的系统内置配置,无法…

外包干了2年,技术退步明显

先说一下自己的情况&#xff0c;研究生&#xff0c;19年进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

Android开发中遇到最难的问题,app架构图

前言 这份Android面试真题涵盖了图片&#xff0c;网络和安全机制&#xff0c;网络&#xff0c;数据库&#xff0c;插件化、模块化、组件化、热修复、增量更新、Gradle&#xff0c;架构设计和设计模式&#xff0c;Android Framework 、Android优秀三方库源码等。适合中高级工程…

Windows安装MySQL详细教程

1.1 下载MySQL压缩包 官网下载链接[点击跳转] 按图中选择&#xff0c;然后点击【Download】 点击图中箭头所指方向直接下载 1.2 解压下载好的压缩包后找到【bin】文件夹&#xff0c;并记下文件路径&#xff08;下文将以路径 D:\mysql-8.0.36-winx64\bin 为例&#xff09; 1.…

JavaScript实现点击鼠标弹钢琴的效果

思路&#xff1a; 图片设置宽900px&#xff0c;找到鼠标按下时的x坐标和img距离body的x坐标&#xff0c;两个值相减&#xff0c;然后除100取整&#xff0c;赋值给a&#xff0c;通过判断a的值来确定放出那个音乐。 完整代码&#xff1a; <!DOCTYPE html> <html lan…

【DAY05 软考中级备考笔记】线性表,栈和队列,串数组矩阵和广义表

线性表&#xff0c;栈和队列&#xff0c;串数组矩阵和广义表 2月28日 – 天气&#xff1a;阴转晴 时隔好几天没有学习了&#xff0c;今天补上。明天发工资&#xff0c;开心&#x1f604; 1. 线性表 1.1 线性表的结构 首先线性表的结构分为物理结构和逻辑结构 物理结构按照实…

python GPU加速 以numba为例

GPU编程(CUDA) GPU(图形处理单元)&#xff0c;多核系统&#xff0c;而现今的大多数CPU也属于多核系统&#xff0c;但它们之间还是存在很大的区别: CPU适合执行复杂的逻辑&#xff0c;比如多分支&#xff0c;其核心比较重(复杂)GPU适合执行简单的逻辑&#xff0c;大量的数据计…

JVM内部世界(内存划分,类加载,垃圾回收)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JVM内部世界(内存划分,类加载,垃圾回收) 关于JVM的学习主要掌握三方面: JVM内存区的划分类加载垃圾回收 一.JVM内存区的划分 当一个Java进程开始执行时,JVM会首先向操作系统申…

给数字人生成加上界面,基于ER-NeRF/RAD-NeRF/AD-NeRF,Gradio框架构建WEBUI,使用HLS流媒体,实现边推理边播放——之一:在WEBUI中实时输出服务器控制台日志

前言 目前数字人实现技术众多&#xff0c;我这里采用基于ER-NeRF&#xff0c;在这里可以看到其介绍&#xff1a;ICCV 2023 | ER-NeRF: 用于合成高保真Talking Portrait的高效区域感知神经辐射场-https://zhuanlan.zhihu.com/p/644520609ER-NeRF的项目地址&#xff1a;https://…

十四、重写与多态

重写、多态 上一讲是&#xff0c;子类对父类横向上的扩展 这一讲是&#xff0c;子类对父类纵向上的扩展 方法重写 使用override关键字重写父类的方法 将父类原本方法的逻辑更新成新版本的逻辑 注&#xff1a;仅能重写可见的父类成员&#xff0c;并且重写要保持签名一致。 签名一…

第五节 JDBC驱动程序类型

JDBC驱动程序是什么&#xff1f; JDBC驱动程序在JDBC API中实现定义的接口&#xff0c;用于与数据库服务器进行交互。 例如&#xff0c;使用JDBC驱动程序&#xff0c;可以通过发送SQL或数据库命令&#xff0c;然后使用Java接收结果来打开数据库连接并与数据库进行交互。 JDK…

Java中常见的 IO 方式

冯诺依曼结构中计算机结构被分为 5 大部分&#xff1a;运算器、控制器、存储器、输入设备、输出设备&#xff0c;输入设备向计算机输入数据&#xff0c;输出设备接收计算机输出的数据。从计算机结构的视角来看的话&#xff0c; I/O 描述了计算机系统与外部设备之间通信的过程。…

JMeter VS RunnerGo :两大主流性能测试工具对比

说起JMeter&#xff0c;估计很多测试人员都耳熟能详。它小巧、开源&#xff0c;还能支持多种协议的接口和性能测试&#xff0c;所以在测试圈儿里很受欢迎&#xff0c;也是测试人员常用的工具&#xff0c;不少企业也基于JMeter建立起自己的自动化测试能力&#xff0c;提升工作效…