一个案例深入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这些东西? 解释之前, ...
随机推荐
- windows服务器下IIS7 安装URL Rewrite(URL重写)模块
URL Rewrite Module是一个基于规则的URL重写引擎,用于在URL被Web服务器处理之前改变请求的URL.对于动态Web应用程序,它可以为用户和seo/seo.html" ta ...
- FM收音机 RDS的强大功能
FM收音机 RDS的强大功能 分类: MTK2011-04-26 16:06 14889人阅读 评论(6) 收藏 举报 交通公告体育音乐娱乐教育 前言 随着发展,会有越来越多的电台具有RDS广播功能, ...
- TweenLite JS版
今早逛网站看到下面这个帖子: 译~GreenSock动画平台(GSAP)的JavaScript版本入门 这个就是做ActionScript 的时候用得最多的第三方缓动包TweenLite了, 就此标记 ...
- codis 新版本 CodisLabs 编译安装
codis 3.0 版本编译安装 # 首先安装 go 语言 wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz ...
- java web系统优化, mysql查询优化
1. 采用数据库连接池技术 2. 优化sql语句格式, 比如用PreparedStatement代替Statement, 前者避免重复编译, 后者每次都需要对数据库进行解析编译, 降低数据库的访问效率 ...
- s3c2440的GPIO驱动
多个通用的GPIO,同时这些端口也拥有一些复用功能(如ADC输入),有部分端口只能输入,有部分端口只能输出,今天我们来看看如何设置一个GPIO的输出电平以及如何获取一个端口的GPIO电平 对GPIO进 ...
- 微信小程序之----navigator页面跳转
navigator navigator跳转页面样式分为两种一种是左上角带返回按钮跳转到新的页面,另一种不带即在本页跳转,通过控制redirect属性 .js <view> <navi ...
- CSS实现导航条Tab切换的三种方法
前面的话 导航条Tab在页面中非常常见,本文说详细介绍CSS实现导航条Tab的三种方法 布局 根据上图所示,先规定几个定义,上图的模块整体叫做导航,由导航标题和导航内容组成.要实现上图所示的布 ...
- VS2013 opencv2.4.8
[转]http://my.phirobot.com/blog/2014-02-opencv_configuration_in_vs.html vs2010+opencv2.4.0:http://www ...
- Oracle 事件
Oracle 的事物 事物是设么 事物是用于高正数据的一致性,他由一组相关的dml语句组成(增加删除语句),这组语句要么全部成功要不全部失败. 如:网上转账. 1)设置保存点 Savepoint a1 ...