一个案例深入Python中的__new__和__init__
准备
在Python中,一切皆对象。
既然一切皆对象,那么类也是对象,我们暂且称之为 类对象。来个简单例子(本篇文章的所有案例都是运行在Python3.4中):
![](/assets/blank.gif)
class foo():passprint(id(foo)) print(type(foo))# 结果: # 46627056 # <class 'type'>
![](/assets/blank.gif)
如果想深入了解一下,可以看:深刻理解Python中的元类(metaclass)
引入
最近在阅读tornado源码,发现在其源码中有很多类是这样的:
![](/assets/blank.gif)
class HTTPServer(TCPServer, Configurable,httputil.HTTPServerConnectionDelegate):def __init__(self, *args, **kwargs):# Ignore args to __init__; real initialization belongs in# initialize since we're Configurable. 就是说默认的__init__初始化方法不在起作用了,改为了initialize方法进行初始化pass
![](/assets/blank.gif)
或者是干脆没有__init__ ,只写了个initialize方法来替代。
所以心生疑惑,tornado是如何做到这一点的?
正题
接下来我们来了解一下,Python解释器是如何创建对象的。
大家可能对Python中的__init__方法很熟悉,认为他是实例化类时调用的第一个方法。但其实他并不是。实例化时调用的第一个方法其实是__new__方法。
好了,接下来是重点:
1 当我们实例化A类对象时,Python中首先调用的是该A类对象的__new__方法,如果该A类对象没有定义__new__方法,则去父类中依次查找,直到object类
2 object类有一个__new__方法,该方法接收一个参数(一般为类对象),将该参数进行实例化并返回一个对象
3 Python解释器会将调用__new__方法并将A类对象作为第一个参数传入,最后会返回一个对象(这个对象就是A类的实例对象,我们称之为a1)
4 Python解释器默认会调用a1对象的__init__方法,并将参数传入。
来一个例子验证一下:
![](/assets/blank.gif)
class asd(object):def __new__(cls, *args, **kwargs):print('asd.__new__() is running. cls id is %s'%id(cls))r = super(asd,cls).__new__(cls)print('r_id is %s'%id(r))return rclass bnm(asd):def __init__(self,name):print('bnm.__init__() is running, self id is %s'%id(self))self.name = nameprint('bnm.name is %s'%(self.name))print('asd_id is %s'%id(asd)) print('bnm_id is %s'%id(bnm)) o1 = bnm('ni') print('o1_id is',id(o1))# asd_id is 49838320 # bnm_id is 49838768 # asd.__new__() is running. cls id is 49838768 # r_id is 49848400 # bnm.__init__() is running, self id is 49848400 # bnm.name is ni # o1_id is 49848400注意 : bnm 和 cls 是同一个对象! r 和 o1 也是同一个对象 !
![](/assets/blank.gif)
应用
仿tornado实现自定义类的初始化方法:
![](/assets/blank.gif)
定义类时,只要继承了asd类,就会将initialize方法作为初始化方法,是不是感觉很(wu)酷(lun)炫(yong)?
一个案例深入Python中的__new__和__init__相关推荐
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- python中__init__后面加特殊符号_详解Python中的__new__、__init__、__call__三个特殊方法...
__new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self) __init__ : 对象的初始化, 是一个实例方法,第一个参数是sel ...
- python中的__new__和__init__
一.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候. 这样便是__init ...
- Computer:字符编码(ASCII编码/GBK编码/BASE64编码/UTF-8编码)的简介、案例应用(python中的编码格式及常见编码问题详解)之详细攻略
Computer:字符编码(ASCII编码/GBK编码/BASE64编码/UTF-8编码)的简介.案例应用(python中的编码格式及常见编码问题详解)之详细攻略 目录 符串编码(ASCII编码/GB ...
- Python中:self和__init__的含义 + 为何要有self和__init__
为什么80%的码农都做不了架构师?>>> 本文转自: http://www.crifan.com/summary_the_meaning_of_self_and___init_ ...
- python init self_转载--------Python中:self和__init__的含义 + 为何要有self和__init__
背景 Python中的self,__init__的含义是啥?为何要有self,__init这些东西? 解释之前,先说几句 1.到目前为止,我虽然也已写了不算很少的python的代码,但是,还真的没有太 ...
- Python中的__new__()方法的使用
__new__() 函数只能用于从object继承的新式类. 先看下object类中对__new__()方法的定义: class object: @staticmethod # known cas ...
- python中的__new__概念(工厂
__new__方法实际上在__init__方法之前执行,用于创建类的实例.然而__init__方法负责实例创建后对其进行自定义,__new__方法才是实际上创建并返回实例的方法. __new__方法的 ...
- python中_new_和_init_的区别_Python 中的__new__和__init__的区别
[同] 二者均是Python面向对象语言中的函数,__new__比较少用,__init__则用的比较多. [异] __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是 ...
- python打开一个文件-在“Python”中如何“尝试/抓住”打开一个文件?
一开始,它有助于防止您在尝试中引入的问题-终于-例如. 结构化方式,如果在尝试打开该文件时抛出异常,那么永远不会将打开的文件绑定到名称f,导致finally子句中的NameError(如果f从未在范围 ...
最新文章
- 克里斯坦森的破坏性创新—《可以量化的管理学》
- EDM数据营销概念简要介绍
- java k线绘制,用Java绘制K线图[Java编程]
- vc动态生成按钮并响应
- 知识点讲解一:代理ip中的proxies
- 如何选择一款优秀的儿童读写台灯?
- 社区 正式发布了跨平台的 CoreWCF 0.1.0 GA
- 设计干货素材|使用纹理背景的技巧
- 大佬 Python 对阵新秀 Julia ,谁能问鼎机器学习和数据科学?
- 深入浅出Node.js(一):什么是Node.js
- ev3 android,乐高®头脑风暴教育机器人EV3编程
- Redfish协议测试工具–Postman
- JS 获取当前星期几/周几
- 4.7 Case Study on Sandy Bridge C…
- 关于视频字幕(有无外挂字幕)的提取死磕一天的总结
- 开源OceanBase如何与Prometheus与Grafana监控结合
- 关于ADS的二次谐波和高次谐波牵引
- 计算机夏令营英语自我介绍,夏令营英语自我介绍
- C/C++的就业,发展方向
- 分库分表实战(8):激流勇进 — 千万级数据优化之加缓存