一个案例深入Python中的__new__和__init__
准备
在Python中,一切皆对象。
既然一切皆对象,那么类也是对象,我们暂且称之为 类对象。来个简单例子(本篇文章的所有案例都是运行在Python3.4中):
class foo():
pass print(id(foo))
print(type(foo)) # 结果:
#
# <class 'type'>
如果想深入了解一下,可以看:深刻理解Python中的元类(metaclass)
引入
最近在阅读tornado源码,发现在其源码中有很多类是这样的:
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
或者是干脆没有__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__方法,并将参数传入。
来一个例子验证一下:
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 r class bnm(asd): def __init__(self,name):
print('bnm.__init__() is running, self id is %s'%id(self))
self.name = name
print('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 也是同一个对象 !

应用
仿tornado实现自定义类的初始化方法:
class asd(object):
def __new__(cls, *args, **kwargs):
r = super(asd,cls).__new__(cls)
r.initialize(*args)
return r class bnm(asd): def initialize(self):
print('bnm_initialize is running') class foo(asd): def initialize(self,name):
self.name = name
print('foo_initialize is running, my name is %s' %(self.name)) r = bnm()
r1 = foo('linghuchong') # bnm_initialize is running
# foo_initialize is running, my name is linghuchong
定义类时,只要继承了asd类,就会将initialize方法作为初始化方法,是不是感觉很(wu)酷(lun)炫(yong)?
一个案例深入Python中的__new__和__init__的更多相关文章
- Python中的__new__和__init__
Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...
- python中的__new__与__init__,新式类和经典类(2.x)
在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...
- python中的__new__、__init__和__del__
__new__.__init__.__del__三个方法用于实例的创建和销毁,在使用python的类中,我们最常用的是__init__方法,通常称为构造方法,__new__方法几乎不会使用,这篇文章是 ...
- Python 中的__new__和__init__的区别
[同] 二者均是Python面向对象语言中的函数,__new__比较少用,__init__则用的比较多. [异] __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是 ...
- 详解Python中的__new__、__init__、__call__三个特殊方法(zz)
__new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)__init__ : 对象的初始化, 是一个实例方法,第一个参数是self ...
- python 中的__new__与__init__
在Python中的class中有两个方法__new__与__init__,有什么区别呢? class TestCls(): """docstring for TestCl ...
- Python中的__new__()方法与实例化
@Python中的__new__()方法与实例化 __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...
- Python中:self和__init__的含义 + 为何要有self和__init__
Python中:self和__init__的含义 + 为何要有self和__init__ 背景 回复: 我写的一些Python教程,需要的可以看看 中SongShouJiong的提问: Python中 ...
- 转载--------Python中:self和__init__的含义 + 为何要有self和__init__
背景 回复:我写的一些Python教程,需要的可以看看,中SongShouJiong的提问: Python中的self,__init__的含义是啥?为何要有self,__init这些东西? 解释之前, ...
随机推荐
- SQLite Lemon 语法分析器学习与使用
本文是浙江大学出版社的<LEMON语法分析生成器(LALR 1类型)源代码情景分析>学习笔记. 用到的Windows下的编译器介绍MinGW(http://www.mingw.org/): ...
- JAVA基础--单例模式
public class Singleton02 { // 私有的静态的类变量 private static Singleton02 instance = null; // 私有的构造方法 priva ...
- UITableView回调和table相关成员方法详解
http://blog.csdn.net/kingsley_cxz/article/details/9123959 1.UITableView的datasource实现: //回调获取每个sectio ...
- iOS 8自定义动画转场上手指南
原文:http://www.cocoachina.com/ios/20150126/11011.html iOS 5发布的时候,苹果针对应用程序界面的设计,提出了一种全新的,革命性的方法—Storyb ...
- webform中 ajax调用后台方法(非webservice)
方法一:通过创建一个没有内容的窗体 后台: public partial class Ajax_ShoppingCart : System.Web.UI.Page { bookdbDataContex ...
- 如何解决Visual Studio2012 与此版本的Windows不兼容
解决方案: http://www.microsoft.com/zh-CN/download/details.aspx?id=36020 下载更新
- Tsinsen-1487:分配游戏【树状数组】
首先一定要看到x + y + z = N这个条件,没看到就世界再见了. 赢的人得分需要大于等于2,那么无非就是 (x, y), (x, z), (y, z), (x, y, z) 大于其他的点.但是考 ...
- jenkins 构建时,取消构建测试类
如图 点击配置,添加clean install -Dmaven.test.skip=true 保存即可
- 公众号第三方平台开发-aes解密失败
公众号第三方平台开发-aes解密失败 问题:本地启动项目,配置域名,测试微信公众号,系统正常运行:将项目部署到测试环境执行同样的操作,系统报错,错误异常:aes解密失败..... 调试--寻找问题-- ...
- 安卓弹出对话框——Alertdialog(一)
首先看各种样式的对话框: 我们看到,Dialog有很多的子类实现,所以我们要定义一个对话框,使用其子类来实例化一个即可,而不要直接使用Dialog这个父类来构造. 二.AlertDialog 今天我们 ...