一个案例深入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这些东西? 解释之前, ...
随机推荐
- implemented loader.php
http://stackoverflow.com/questions/11787176/manage-url-routes-in-own-php-framework This is how i imp ...
- Github for Windows使用图文教程_西西软件资讯
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- 关于OC和Swift使用GIT创建项目
1.先进入码云,点击自己的头像 -> ,2.里面有一个SSH公钥,点击 ,3.之后在终端输入 ssh-keygen -t rsa -C “xxxxx@xxx.com”,注意:”” 要用英 ...
- Nginx负载均衡和Keepalived的安装设置
一.Nginx设置负载均衡 (1)upstream的配置 http { upstream backend { #这里设置后台分发的服务器族群,有多少个可以添加,同时设置查询策略 server 192. ...
- css(一)-- 概述以及引入方式
概述 层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言.CSS不仅可 ...
- STM32-USB详细使用说明(转)
源:STM32-USB详细使用说明 附件HID的双向通信 亮点STM32开发板充实了USBHID数据发送和接收例程(STM32固件库3.5 USB库3.4)
- ubuntu12.04+fuerte 下跑通lsd-slam——数据集
lsd-slam(下载链接:https://github.com/tum-vision/lsd_slam)提供了两种方法,一种是用数据集(下载地址http://vision.in.tum.de/lsd ...
- Vector类
/* * Vector的特有功能 * * Vector出现较早,比集合更早出现 * * 1:添加功能 * public void addElement(Object obj);//用add()替代 * ...
- JavaScript(一)---- 概述
JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标 ...
- PHP+AJAX 地区三级联动代码
<html><head><meta http-equiv="Content-Type" content="text/html; charse ...