python--type,object,元类,__new__关系
上篇文章中通过代码方式,重点讲解了:
- __new__和__init__之间的关系,前者是用来创建类实例,后者用来初始化类实例,它两配合使用,才完整生成一个类实例。
- object和type之间的关系,前者负责继承这块工作,后者负责类型定义这块工作。即所有的对象都起源于object,所有的对象最终都是type这个类型。
本文将重点介绍元类和元类的创建。
1.什么是元类
元类是创建类的类。如何理解这句话,先看以下代码:
class B():pass
b=B()
print(b.__class__)
print(B.__class__)
print(object.__class__)
#打印情况:
<class '__main__.B'>
<class 'type'>
<class 'type'>
上述代码中b是由类B构建的,因此b的类型(通过__class__属性查看)是<class ‘main.B’>,而后面B和object的类型都是type,同理,这说明B和object都是由type这个类创建的,即type可以用来创建类。
能够创建类的类,我们称作元类,type就是最原始的一个元类。
2.type如何创建类
首先声明:type在python中有两个身份:
1.type当做函数用,同__class__属性作用相同,返回对象的类型
2.type当做类用,是元类,用于创建其它的类。
下面是当做类用。
语法:
type(类名称字符串,类继承的元组,类的属性/函数字典)
三个的参数含义和类型都在上面规定了。下面代码用type类创建了一个类A,并为类A创建了一个name属性和一个show函数(注意不是shows函数,尽管定义的时候是shows)
def shows(self,name):print(name)
#用type类创建类A
A=type("A",(object,),{'name':"bob",'show':shows})
aa=A()
print(aa.name)
aa.show("wangwu")##输出结果
bob
wangwu
3.自定义元类
默认情况下,所有类都是由type元类创建,当然也可以自定义元类,这样该类的__class__属性就不是type了,而是该自定义元类。
语法:自定义元类必须要显示继承于type类。
class XXMetaClass(type):pass
4.设置类的元类为自定义元类
class XXClass(object,metaclass=XXMetaClass):pass
5.实例演练
下面代码中定义了一个元类TMetaclass,和三个普通类,且这三个普通类都是通过该元类生成的。由下面的打印结果可知,元类的__new__函数返回的值正是各个类。也就是说,在元类中是通过__new__函数生成类的。
class TMetaclass(type):def __new__(cls, name, bases, attrs):print("__new__参数:",cls, name, bases, attrs,'\n')print("__new__返回类型: ",type.__new__(cls, name, bases, attrs),'\n')return type.__new__(cls, name, bases, attrs)#生成相应的类,并返回class Test1(dict,metaclass=TMetaclass):def __init__(self, **kw):super(T, self).__init__(**kw) def p(self):print("ppp")passclass Test2(Test1):passclass Test3(Test2):pass#结果打印:
__new__参数: <class '__main__.TMetaclass'> Test1 (<class 'dict'>,) {'__module__': '__main__', '__qualname__': 'Test1', '__init__': <function Test1.__init__ at 0x000002F08653E8C8>, 'p': <function Test1.p at 0x000002F08653E7B8>, '__classcell__': <cell at 0x000002F0864BA1C8: empty>} __new__返回类型: <class '__main__.Test1'> __new__参数: <class '__main__.TMetaclass'> Test2 (<class '__main__.Test1'>,) {'__module__': '__main__', '__qualname__': 'Test2'} __new__返回类型: <class '__main__.Test2'> __new__参数: <class '__main__.TMetaclass'> Test3 (<class '__main__.Test2'>,) {'__module__': '__main__', '__qualname__': 'Test3'} __new__返回类型: <class '__main__.Test3'>
4.类实例的生成过程
分为两个阶段:
1.类的生成:由元类生成;
2.实例的生成:由上述生成的类接着生成。
具体描述:
结合上一篇文章中,我们总结出生成一个类实例的全部过程:
1.类首先查找内部__metaclass__属性是否被自定义元类赋值,若赋值则准备用该自定义元类生成类,否则用type作为元类生成类;
2.解释器调用该元类的__new__函数(该函数为静态函数),并将要实例化的类中定义的各种属性传递给该函数固定的四个参数:其中cls是该元类本身,name是要被实例化的类的类名,bases是该类父类组成的元组,attrs则是该类{属性名:属性值,函数名:函数对象}组成的字典。
3.最终通过type类生成该类,并返回。
4.该类生成后,调用类中的__new__函数(该函数是静态函数)创建该类的实例,并返回该实例;
5.该实例接着调用它的__init__函数初始化实例,这样一个完整的实例就被生成出来了。
5,自定义元类的核心
由于是元类构建了类,因此若要更改某些固定类(str,int等)的用法,就必须在元类中做文章了。而元类的核心是__new__函数,自然在该函数内做文章。比如可以通过atrris字典为元类添加新的属性和函数,或改变以往的属性或函数等。这样的改变会传播到所有用该元类创建的类中。
总结:
__new__函数:
1.在元类中该函数用来构建类本身;
2.在类中,该函数用来构建类实例;
6. 类函数调用方式
def A():def show(self,name):print(name)
a=A()
#我们的调用方式:
a.show("hello")
#实际解释器的调用方式,这个a实例填充了self这个参数的位置
A.show(a,"hello")
参考文献:
1.深刻理解Python中的元类(metaclass)以及元类实现单例模式
2. 道生一,一生二
3. 一篇文章让你彻底搞清楚Python中self的含义
python--type,object,元类,__new__关系相关推荐
- python语法之元类与type()函数
元类 千万不要被所谓"元类是99%的python程序员不会用到的特性"这类的说辞吓住.因为每个中国人,都是天生的元类使用者 学懂元类,你只需要知道两句话: 道生一,一生二,二生三, ...
- 深刻理解Python中的元类(metaclass)以及元类实现单例模式
在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例模式的那一节有些疑惑.因此花了几天时间研究下元类这个概念.通过学习元类,我对pyt ...
- Python中的元类及元类实现的单例模式
https://www.cnblogs.com/tkqasn/p/6524879.html 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元 ...
- Python中的元类
Python中的元类 Python一切皆对象,所以类也是对象. 我们知道,对象是通过类实例化创建出来的.但我们创建类时并没有进行实例化操作,为什么类也是对象呢? 类既然是对象,类肯定是另外某个类的实例 ...
- python中的元类Metaclass
python中的元类Metaclass 理解元类之前需要学习的知识 如果说让我们创建一个类,最先想到的肯定是用class创建,当我们使用class创建类的时候,python解释器自动创建这个对象,但是 ...
- Python中的元类是什么?
元类是什么,我们将它们用于什么? #1楼 请注意,此答案适用于2008年编写的Python 2.x,元类在3.x中略有不同. 元类是使"类"工作的秘诀. 新样式对象的默认元类称为& ...
- Python基础:元类
一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...
- python中的元类_Python中的元类(metaclass)
提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自身有关,但仍然觉得不太明白,希望大家可以给出一些实际的例子和代码片段以帮助理 ...
- python最详细 ---- 元类 __metaclass__
元类最常用作类工厂.就像通过调用类创建类的实例一样,Python通过调用元类创建一个新类(当它执行'class'语句时).结合常规__init__和__new__方法,元类因此允许您在创建类时执行&q ...
- python高级(元类、自定义元类)
什么是元类(metaclass)? 元类是类的类,是类的模板 元类的实例为类,正如类的实例为对象 class Foo: pass t1=Foo() #t1是通过Foo类实例化的对象 prin ...
最新文章
- EDM营销中HTML邮件设计方法和技巧
- 运维软件PE工具箱下载附制作、安装教程
- 重新学.Net[四]——效率和安全
- 参数详解 复制进程_如何优化PostgreSQL逻辑复制
- 深度学习TF—10.循环神经网络RNN及其变体LSTM、GRU实战
- k8s重要概念及部署k8s集群
- 分布式系统接口幂等性
- java学习第123天,p750-761(05/23)干得漂亮
- IOS-App Store 提审应用步骤
- Shopee本地店和跨境店物流及收款方式介绍
- 【直击DTCC】宝存CEO阳学仕:如何保障SSD的IO确定性?
- html 写字板 乱码,Win7系统写字板打开文档出现乱码的两种解决方法
- python中的if判断,和while循环的用法
- EXCEL多列内容合并且中间加字符串
- QPST 2.7.460 高通产品专用支持套件 (Qualcomm Product Support Tools)
- c3p0,DBCP,Druid(德鲁伊)数据库连接池
- linux下使用命令行来调节系统音量的两种方法amixer和pactl
- gcc 内联汇编用法介绍
- matlab时域计算频率,基于MATLAB 的信号时域采样及频率混叠现象分析
- php lodop,打印控件Lodop6.0版发布
热门文章
- mysql之两阶段提交
- spring中的控制反转和依赖注入之间的关系
- 【粉丝专享福利】联合6大博主送出18本ChatGPT扫盲教程实体书,文末有惊喜
- 整理的游戏服务器架构资料
- 失业3个月终于上岸,分享几点经验:不要转行,不要一份简历通吃,要重复投简历,要主动降薪!...
- JSON Schema 详解
- 程序员的nginx技能包(3)——静态资源管理,资源井井有条,生活风花雪月
- 内是不是半包围结构_半包围结构有什么字?
- js中复选框checkbox如何判定为被选中
- 阿里巴巴新零售数据库设计(简化版)