在 Python 中,一切皆对象。
既然一切皆对象,那么类也是对象,我们暂且称之为 类对象。来个简单例子 (本篇文章的所有案例都是运行在 Python3.4 中):
- class foo():
- pass
- print(id(foo))
- print(type(foo))
- # 结果:
- # 46627056
- # <class 'type'>
如果想深入了解一下,可以看:
最近在阅读 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 实现自定义类的初始化方法:
View Code
- 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)?
来源: