准备

在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__的更多相关文章

  1. Python中的__new__和__init__

    Python中的__new__和__init__ 写了这么多的class,现在才知道还有个__new__方法, 那么它和__init__有什么区别呢? class TestCls(): "& ...

  2. python中的__new__与__init__,新式类和经典类(2.x)

    在python2.x中,从object继承得来的类称为新式类(如class A(object))不从object继承得来的类称为经典类(如class A()) 新式类跟经典类的差别主要是以下几点: 1 ...

  3. python中的__new__、__init__和__del__

    __new__.__init__.__del__三个方法用于实例的创建和销毁,在使用python的类中,我们最常用的是__init__方法,通常称为构造方法,__new__方法几乎不会使用,这篇文章是 ...

  4. Python 中的__new__和__init__的区别

    [同] 二者均是Python面向对象语言中的函数,__new__比较少用,__init__则用的比较多. [异] __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是 ...

  5. 详解Python中的__new__、__init__、__call__三个特殊方法(zz)

    __new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)__init__ : 对象的初始化, 是一个实例方法,第一个参数是self ...

  6. python 中的__new__与__init__

    在Python中的class中有两个方法__new__与__init__,有什么区别呢? class TestCls(): """docstring for TestCl ...

  7. Python中的__new__()方法与实例化

    @Python中的__new__()方法与实例化   __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...

  8. Python中:self和__init__的含义 + 为何要有self和__init__

    Python中:self和__init__的含义 + 为何要有self和__init__ 背景 回复: 我写的一些Python教程,需要的可以看看 中SongShouJiong的提问: Python中 ...

  9. 转载--------Python中:self和__init__的含义 + 为何要有self和__init__

    背景 回复:我写的一些Python教程,需要的可以看看,中SongShouJiong的提问: Python中的self,__init__的含义是啥?为何要有self,__init这些东西? 解释之前, ...

随机推荐

  1. rsync+inotify实现数据的实时备份

    一.rsync概述 1.1.rsync的优点与不足 rsync与传统的cp.tar备份方式相比,rsync具有安全性高.备份迅速.支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需 ...

  2. sublime text3 Emmet (原zenCoding)安装方法

    1.安装使用Package Control组件安装 (1)打开控制台 (mac)control+`; (win)ctrl+` (2)复制一下代码并回车 import urllib.request,os ...

  3. Win7下 IIS+PHP(ZendLoader)+MySQL

    这里使用的是傻瓜式安装方式 下载php-5.3.18-nts-Win32-VC9-x86.msi,Win7下可执行文件.(下载地址 http://pan.baidu.com/s/1qvJCA) 执行到 ...

  4. 如何把程序钉到Windows7任务栏(修正版)

    源:如何把程序钉到Windows7任务栏(修正版) 在CSDN论坛看到有网友提问如何把程序钉到Windows7的任务栏,ccrun(妖哥)对这个问题很感兴趣,于是google了一下,没有找到相关的AP ...

  5. postgresql 抽样查询

    curl -GET 'http://****/query' --data-urlencode "db=db" --data-urlencode "q=SELECT las ...

  6. javascript高级程序设计 重读系列

    1.基本概念.数据类型.函数 1.1 数据类型 ECMAScript中有5种简单数据类型:Undefind,Null,Boolean,Number,String 问题:判断变量是否是空值的代码 解析: ...

  7. CDOJ 1268 Open the lightings

    组合数学题.好难啊,请教了Xiang578大神&&看了他题解才会的...... 甩上题解链接:http://blog.csdn.net/xinag578/article/details ...

  8. runtime - associated(关联)

    category和associative作为objective-c的扩展机制的两个特性,category用来扩展类的方法,associative可以用来扩展类的属性.使用associative需要导入 ...

  9. 6、手把手教你Extjs5(六)继承自定义一个控件

    Extjs的开发都可以遵循OOP的原则,其对类的封装也很完善了.自定义一个控件最简单的办法就是继承一个已有的控件.根据上一节的需要,我做了一个Button的子类.首先根据目录结构,在app目录下建立一 ...

  10. Powerbuilder编程技巧 如何获取网页的HTML源码

    直接使用的三种方式 1.  PB内部对象 Inet object 2.  API 函数 3.  Ole中的Microsfot Web 游览器对象 一.Inet object: 1.Inet objec ...