python 元类的call_【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理...
原始type:
type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attributes_dict)" 这种语法来使用时, 在__call__方法内使用又会调用type的__new__和__init__方法来创建classname_string的具体类,并初始化类信息。当type(***)调用完成, classname_string代表的类可以用来创建实例了。
元类调用过程: 原始type元类同理
如下流程:假设是MyMeta元类,而不是原始type元类
例子: MyClass = MyMeta('MyClass', bases, attributes)
my_meta_type=type(MyMeta)MyClass=my_meta_type.__call__(MyMeta,cls,bases,attributes)
在__call__中应该是如下操作:MyClass = MyMeta.__new__(MyMeta, cls, bases, attributes)
meta_class = MyClass.__metaclass__
meta_class.__init__(MyClass, cls, bases, attributes)
return MyClass
最终返回MyClass类
上述元类有一个很令人迷惑的地方,需要注意到,当你的元类是自定义的元类的时候,假设是MyMeta,此时调用的是MyMeta的父元类type的__call__,所以假设MyMeta自定义了__call__,你要知道当调用MyMeta()的时候,该函数并没有被调用,调用的是type的__call__,你定义MyClass对象实例时才会调用该函数。如果你在MyClass对象中也定义了__call__函数,那么假设你定义了一个MyClass的对象myobj,你使用myobj()形式用法时,调用的是MyClass的__call__ 。
总结: 元类处理过程:定义一个类时,使用声明或者默认的元类对该类进行创建,对元类求type运算,得到父元类(该类声明的元类的父元类),调用父元类的__call__函数,在父元类的__call__函数中, 调用该类声明的元类的__new__函数来创建对象(该函数需要返回一个对象(指类)实例),然后再调用该元类的__init__初始化该对象(此处对象是指类,因为是元类创建的对象),最终返回该类。
你可以简单实验以下,自定义俩个元类,该俩个元类是父子关系,在定义一个类,设置使用自定义元类的子元类,发现会调用自定义元类的父元类中call的输出,子元类的call并没有输出,在定义类的对象时才输出了
例子如下:
class SuperMeta(type):
def __call__(metaname, clsname, baseclasses, attrs):
print 'SuperMeta Called'
clsob = type.__new__(metaname, clsname, baseclasses, attrs)
type.__init__(clsob, clsname, baseclasses, attrs)
return clsob
class MyMeta(type):
__metaclass__ = SuperMeta
def __call__(cls, *args, **kwargs):
print 'MyMeta called', cls, args, kwargs
ob = object.__new__(cls, *args)
ob.__init__(*args)
return ob
print 'create class'
class Kls(object):
__metaclass__ = MyMeta
def __init__(self, data):
self.data = data
def printd(self):
print self.data
print 'class created ---------------------'
# 你会发现定义了 Kls 类后输出了SuperMeta 父元类的输出
ik = Kls('arun')
ik.printd()
ik2 = Kls('avni')
ik2.printd()
# 定义Kls对象实例才真的执行了MyMeta的call
为什么type会调用自己的呢,因为type的type还是type, 蛋疼一小会……
附加:
原始type的__call__应该是参数结构应该是:
metaname, clsname, baseclasses, attrs
原始type的__new__
metaname, clsname, baseclasses, attrs
原始type的__init__
class_obj, clsname, baseclasses, attrs
元类的__new__和__init__影响的是创建类对象的行为,父元类的__call__控制对子元类的 __new__,__init__的调用,就是说控制类对象的创建和初始化。父元类的__new__和__init__由更上层的控制,
一般来说,原始type是最初的父元类,其__new__和__init__是具有普遍意义的,即应该是分配内存、初始化相关信息等
元类__call__影响的是创建类的实例对象的行为,此时如果类自定义了__new__和__init__就可以控制类的对象实例的创建和初始化
__new__和__init__ 影响的是创建对象的行为,当这些函数在元类中时,影响创建的是类;同理,当这俩个函数在普通类中时,影响创建的是普通的对象实例。
__call__ 影响()调用行为, __call__是在创建类的时候调用,即: class Test(object): __metaclass__=type, 定义类时就是创建类,此时会调用元类的__call__,如果元类有继承,子元类定义时执行的是父元类的__call__。
如果是普通类实例化对象,调用的是普通类的__call__
有点绕啊。。。
参考:
http://pythoncentral.io/how-metaclasses-work-technically-in-python-2-and-3/
http://stackoverflow.com/questions/2608708/what-is-the-difference-between-type-and-type-new-in-python Florentin的答案
classKls(object):
__metaclass__=MyMeta
def__init__(self,data):
self.data=data
defprintd(self):
printself.data
python 元类的call_【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理...相关推荐
- java 创建对象的init_Java 对象创建过程。init 方法和 clinit方法。
Java 对象创建过程 判断是否加载.分配内存(指针碰撞或者空闲链表).初始化为零值.设置对象头(实例是哪个类的实例.类的元信息位置.GC 分代年龄等).init 方法. Java 虚拟机创建一个对象 ...
- 深入理解JVM的对象创建过程
关于对象创建,有很多种方法.比如可以通过反射,或者通过 new关键字来创建.不管是何种方式,最终都是会创建一个对象.而我们平常工作中最常用的就是通过new关键字来创建对象.对于我们而言,只要new一下 ...
- java方法区对象类型_浅谈Java内存区域与对象创建过程
一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...
- Mybatis--SqlSession对象创建过程
Mybatis--SqlSession对象创建过程 一. 源码阅读 二. 文字总结 三. 图像总结 mybatis是个很方便的框架,其中最重要的无疑就是session对象了.知其然,知其所以然才能不断 ...
- 对象创建过程 流程解析图 详细之极
我们在学的时候,不仅要知其然,还要知其所以然! 所以今天我能总结了一张关于对象创建整体过程流程图.其中包括了 1.对象的创建过程 2.类的加载过程 3.每个类加载过程的讲解 4.类加载器的简单介绍 总 ...
- Java类加载及对象创建过程详解
类加载过程 类加载的五个过程:加载.验证.准备.解析.初始化. 加载 在加载阶段,虚拟机主要完成三件事: 通过一个类的全限定名来获取定义此类的二进制字节流. 将这个字节流所代表的静态存储结构转化为方法 ...
- JVM篇--详解对象创建过程-对象结构-对象访问方式
hello,hello,刚学过的东西瞬间忘记,是我年龄大了还是年龄大了,可我明明才20出头啊(凑不要脸),其实25了,偏题了....今天整理一下关于JVM对象篇的结构,会记录对象创建过程,还有对象的内 ...
- JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
文章目录 前言 零.排序规范 1.happens-before原则 2.找文档位置 一.一线互联网企业关于对象面试题: (后面回答的就是这几个问题) 二.对象创建过程 三.对象在内存中的存储布局 1. ...
- 找对象的过程中,我竟然理解了什么是机器学习!
最近开始了有关机器学习方面知识的学习,自己啃书本的时候一些概念枯燥无味,所以借着做笔记的机会来简单理解其中的一些概念,如有谬误,还望指出.? 什么是人工智能? 我看过很多博客解释什么是人工智能,我觉得 ...
最新文章
- Flask开发服务器启动方式
- mysql 8重置root密码_如何在MySQL 8中重置root密码
- 计算机科学导论学习资料
- kafka 出现Java heap space的解决方法
- 阿里云ECS上LVM磁盘配置
- php 设置post大小_php 修改上传文件大小限制实例详解
- c++学习书籍推荐《Advanced C++》下载
- react生命周期函数_如何优雅的消灭掉react生命周期函数
- [转载] 一文彻底搞懂父类引用指向子类对象问题
- 博途变量类型_PLC数据类型(UDT)
- java executor解读_Java-多线程框架Executor解读
- 焦作一中高考成绩查询2021,焦作高中学校排名2021最新排名,焦作高中排名前十
- TypeError: keys must be str, int, float, bool or None, not tuple,解决 python 中 json 保存不了字典键值为 元组 的问题
- {Java}一个有关类属性初始化的有趣儿情况
- UI控件--时间选择(日期拾取器)
- 2021年中国旅游城市星级饭店总体发展概况分析:营业收入总额874.51亿元[图]
- 计算机学科发表顶级期刊论文,计算机类顶级期刊_计算机顶级期刊_mcs数学与计算机期刊...
- elementUI环形进度条设置渐变色和修改底色
- 分化成功的标志及特异性神经递质的检测
- 常见随身WiFi设备总结