博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个案例深入Python中的__new__和__init__
阅读量:4919 次
发布时间:2019-06-11

本文共 2301 字,大约阅读时间需要 7 分钟。

准备

在Python中,一切皆对象。

既然一切皆对象,那么类也是对象,我们暂且称之为 类对象。来个简单例子(本篇文章的所有案例都是运行在Python3.4中):

class foo():    passprint(id(foo))     print(type(foo))# 结果:# 46627056# 

如果想深入了解一下,可以看:

 

引入

最近在阅读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 rclass 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 rclass 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
View Code

 

定义类时,只要继承了asd类,就会将initialize方法作为初始化方法,是不是感觉很(wu)酷(lun)炫(yong)?

 

转载于:https://www.cnblogs.com/MnCu8261/p/6365665.html

你可能感兴趣的文章
JavaScript 中 call()、apply()、bind() 的用法
查看>>
javascript中实现继承的6种方式
查看>>
CSS水平垂直居中常见方法总结(转)
查看>>
如何居中浮动元素
查看>>
rgba()和opacity的区别
查看>>
盒子模型以及css3指定盒子模型种类的box-sizing
查看>>
JS基础-连续赋值(转)
查看>>
前端解决跨域问题(转)
查看>>
dom元素的增删查改
查看>>
从一张搞笑图看JavaScript的语法和特性
查看>>
JavaScript中双等的使用情况
查看>>
leetcode 20.有效的括号
查看>>
线程安全性
查看>>
SecureCrt自动化
查看>>
移动端页面滚动穿透问题解决方案
查看>>
书:《腾讯传》
查看>>
关于jquery中html()、text()、val()的区别
查看>>
设置html title标题左侧的小图标
查看>>
5、事务,索引
查看>>
如何从思维上应对
查看>>