细说python类3——类的创建过程
细说python类3——类的创建过程
https://blog.csdn.net/u010576100/article/details/50595143
先来介绍一下python的__call__函数,call的作用是什么呢?举个例子来说明一下:
>>> class A(object):
... def __init__(self):
... print 'a'
... def __call__(self):
... print 'call'
...
>>> a=A()
a
>>> a()
call
据说a()这么使用的时候相当于执行a.__call__(),我们暂且这么理解,具体原因请参考专业文档,这里看可能a()没啥用,请继续向后看。
接下来,说一下类的type,
>>> class B:
... def __init__(self):
... print 'b'
...
>>> b=B()
b
>>> type(B)
<type 'classobj'>
>>> B
<class __main__.B at 0x7fdf94c086b0>
>>> type(b)
<type 'instance'>
>>> type(type(B))
<type 'type'>
>>> B
<class __main__.B at 0x7fdf94c086b0>
由上面例子可以看出类,实例的数据类型。
之后用type函数,创建一个类,type()函数,大致需要以下几个参数,第一个是类的name,第二个是这个类的父类,之后是属性。这里name指的是<class __main__.B at 0x7fdf94c086b0>这里面__main__后面跟的字符。为了保持一致,通常与类的名字一样。
>>> A=type('A',(object,),{'name':'aaa'})
>>> A
<class '__main__.A'>
可以看出我们的类A已经创建成功
>>> type(A)
<type 'type'>
但是为什么type(A)类型还是type,而不是<type 'classobj'>呢?因为type(A)和type(type('A',(object,),{'name':'aaa'}))是一样的,我猜classobj就是一个别名,但是我们用最原始的方法没显示别名,所以只显示type,但这不重要,重点是类已经创建了。那么我们自己封装一个类继承type去创建类呢?
>>> class MyType(type):
... def __init__(self,name,bases,dict):
... print 'mytype'
... def __call__(self,*args,**kwargs):
... print 'mytype call'
这里我们参数和type的源码一致,相当于重写了type的init和call,之后写一个B类,把B的__metaclass__指向myType,
>>> class B:
... __metaclass__=MyType
... def __init__(self):
... print 'b'
>>> b=B()
mytype call
>>> b
实例化一个b,可以看到,执行了MyType的init,但是b并没有生成任何东西。
这里解释一下,当执行b=B()时,需要先找到类内部的__metaclass__并执行,按照__metaclass__顺序先来执行__init__创建一个最初的类,类需要实例化,当我们实例化时会调用metaclass的__call__函数(这样使用B(),就解释了上面的call方法),__call__函数内部正常会调用B类里面的__new__方法来创建一个类的对象,之后会调用B里面的__init__函数给对象进行最初的包装(把相关的参数赋值等操作),最后返回这个类的对象,再把这个对象付赋给b,这样就完成了实例化的过程。因为MyType的__call__方法只打印了一串信息,所以这个实例没有值。也就是说正常创建一个实例对象的其实是new而不是init,init只是起到一个赋值的作用。下面代码模拟一下类的实例化过程:
def __call__(self,*args,**kwargs):
print 'mytype call'
re=self.__new__(self,*args,**kwargs)
self.__init__(re)
return re
class B:
__metaclass__=MyType
def __init__(self):
self.name='b'
print 'B'
def __new__(cls,*args,**kwargs):
return object.__new__(cls,*args,**kwargs)
def Func(self):
print 'Func'
def __call__(self):
print 'call'
b=B()
print b
print b.name
执行结果如下:
mytype
mytype call
B
<__main__.B object at 0x7fd84d7ae710>
b
细说python类3——类的创建过程的更多相关文章
- 类和对象的创建过程(元类,__new__,__init__,__call__)
一. type() 1.创建类的两种方式 方式一 class MyClass(object): def func(self,name): print(name) myc = MyClass() pri ...
- python原类、类的创建过程与方法
今天为大家介绍一下python中与class 相关的知识-- 获取对象的类名 python是一门面向对象的语言,对于一切接对象的python来说,咱们有必要深入的学习与了解一些知识 首先大家都知道,要 ...
- 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理
原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...
- python 通过元类控制类的创建
一.python中如何创建类? 1. 直接定义类 class A: a = 'a' 2. 通过type对象创建 在python中一切都是对象 在上面这张图中,A是我们平常在python中写的类,它可以 ...
- 深入理解Java对象的创建过程:类的初始化与实例化
摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...
- python之定义类创建实例
https://www.cnblogs.com/evablogs/p/6688938.html 类的定义 在Python中,类通过class关键字定义,类名以大写字母开头 1 2 >>&g ...
- springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。为了区别不同的异常通常根据异常类型自定义异常类,这里我们创建一个自定义系统异常,如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。
springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑. 1.1 异常处理思路 系统中异常包括两类:预期异常和运行时异常RuntimeEx ...
- Java对象的创建过程:类的初始化与实例化
一.Java对象创建时机 我们知道,一个对象在可以被使用之前必须要被正确地实例化.在Java代码中,有很多行为可以引起对象的创建,最为直观的一种就是使用new关键字来调用一个类的构造函数显式地创建对象 ...
- 理解python的元类
看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...
随机推荐
- nodejs express 部署
一.express 4.x版本之前 全局安装express 命令是 npm install express -g express 4.x版本之后 全局安装express 命令是 npm install ...
- ThinkCMF5.1虚拟机下安装的问题,已成功
官方的解决方案:https://www.kancloud.cn/thinkcmf/faq/1197179 按它的提示,发现阿里云的虚拟主机htdoc同级的目录没有上传权限. 只能把“ThinkCMF文 ...
- Big Data(七)MapReduce计算框架(PPT截图)
一.为什么叫MapReduce? Map是以一条记录为单位映射 Reduce是分组计算
- ThinkPHP中的SQL结果分析
ThinkPHP中的SQL结果分析 在进行结果判断时需要注意. 一.查询SQL: 可能出现的情况:1.查询成功,返回正常数据.2.查询成功,但是没有数据,返回NULL.3.查询错误,写错关键字.结果: ...
- Synchronized 失效原因
Synchronized 同步出现失效 Synchronized ,大家都知道这个是Java 提供的一种原子性内置锁,其实现原理是通过获取对象的监视器monitor进行来实现同步的,只有当线程获取到对 ...
- HDU-6668-Polynomial(数学)
链接: https://vjudge.net/problem/HDU-6668 题意: 度度熊最近学习了多项式和极限的概念. 现在他有两个多项式 f(x) 和 g(x),他想知道当 x 趋近无限大的时 ...
- float浮动导致父元素高度坍塌的原因及清除浮动方法
一.浮动产生原因 一般浮动是什么情况呢?一般是一个盒子里使用了CSS float浮动属性,导致父级对象盒子不能被撑开,这样CSS float浮动就产生了. 本来两个黑色对象盒子是在红色盒子内, ...
- MySQL数据表
创建数据表 CREATE TABLE IF NOT EXISTS ([列名column][类型type][约束可选]) 查看数据表结构 DESC <表名> 修改数据表结构 ALTER ...
- Eigen 矩阵库学习笔记
最近为了在C++中使用矩阵运算,简单学习了一下Eigen矩阵库.Eigen比Armadillo相对底层一点,但是只需要添加头文库即可使用,不使用额外的编译和安装过程. 基本定义 Matrix3f是3* ...
- vue-router的hash模式和history模式,
hash模式背后的原理是onhashchange事件,可以在window对象上监听这个事件: window.onhashchange = function(event){ console.log(ev ...