Python作为一门易用性见长的语言,看上去简单,却仍然有很多值得一说的内容,因此这个系列会把Python中比较有意思的地方也给科普一遍。而另一方面,关于Python的学习资料在中文互联网上已经随处可见,虽然大都是入门向、实用向的,不过资料覆盖面也已经挺全乎的了。所以这个系列将会着重去讲一些现有中文资料里不常见到的硬核内容,尝试去用另外一个视角去讲解Python,也因此,这个系列更适合有最基本Python使用基础,对基本概念有初步认识的读者。
本文将会着重讲讲关于类的事情,尤其是类的方法。主要从原理的角度讲解类和方法的本质,以方便理解。而对于略过的部分,后续也将考虑另开文章进行详细讲解。
对象是如何被构造的
首先,让我们来一块想一个终极问题——对象是怎么来的?这看起来答案显而易见——对象不就是构造函数构造出来的么?但实际上这么说并不准确,要说到Python对象是如何被构造的,就不得不说三个特殊的方法:__new__
、 __init__
和 __del__
。
首先 __init__
应该用过Python的都不陌生,但是另外两个分别是什么就未必了解了。我们来看一个最为直观的例子
class T:
def __init__(self, x, y):
print('Initializing T', x, y)
self.x = x
self.y = y
def __new__(cls, *args, **kwargs):
print('Creating new T', args, kwargs)
return object.__new__(cls)
def __del__(self):
print('Deleting T')
if __name__ == '__main__':
t = T(1, 2)
print('t is initialized.')
# Creating new T (1, 2) {}
# Initializing T 1 2
# t is initialized.
# Deleting T
通过这个例子会发现,执行的顺序大致如下图所示
Python对象的生命周期
具体来说,分为以下几个阶段:
- “从无到有”——通过
__new__
方法,创建一个新的初始对象,并将此模板对象作为self
传入给后续的__init__
方法。 - “组装配件”——通过
__init__
方法,基于之前生成的函数初始对象进行装饰(也就是常说的字段赋值)。这一过程类似于工厂模式,并非在创造而是在加工。经过了这一步处理的对象,才算是正式完成了对象的初始化,这一初始化完毕的对象也会传回到调用构造函数之处,作为一个真正的实例参与到业务逻辑中。 - “对象销毁”——当对象的生命周期结束之时,通过
__del__
方法,处理掉当前对象下于初始化阶段组装的全部“配件”。处理完毕后,该对象将被销毁,对象的生命周期就此终止。
也就是说,我们所日常认知的Python对象,其实是经历了__new__
和__init__
两个阶段构造出来的实例,也正是这样构造出来的对象,支撑了我们在Python中几乎所有的数据模型及其业务逻辑。
延伸思考1: __new__
和 __del__
分别有什么样的应用场景?
延伸思考2:如果需要定义一个类,且需要在任意时刻了解其所有处于活动状态的实例对象并进行查询,应该如何去实现?
欢迎评论区讨论!
类与对象的本质
首先说到Python中的类,关于类及其方法的基本介绍,可以参考