谁是真正的构造函数
我们通常把__init__ 称为构造方法,这是从其他语言借鉴过来的术语。其实,用于构建实例的是特殊方法__new__:这是个类方法(使用特殊方式处理,因此不必使用@classmethod装饰器),必须返回一个实例。
返回的实例会作为第一个参数(即self)传给__init__ 方法。因为调用__init__ 方法时要传入实例,而且禁止返回任何值,
- 所以__init__ 方法其实是“初始化方法”。 真正的构造方法是__new__。
我们几乎不需要自己编写__new__ 方法,因为从object 类继承的实现已经足够了。
实例创建过程
当使用"类名([实参])"创建实例对象时,Python解释器的主要处理过程包括2大步:
1.调用特殊方法__new__()创建实例对象
首先会查找该类对象是否实现了特殊方法__new__(),如果没有实现,则根据MRO顺序在父类中依次查找,直到类对象object
2.调用特殊方法__init__()返回创建的实例对象
new()返回的实例对象会作为实参被自动传递给__init__()的第一个形参self。
下面我们通过一个示例来展示这两大步,并且通过内置函数id( )来验证实例的创建过程。
class Parent(object):
def __new__(cls, *args, **kwargs):
print("父类的__new__()被调用,其形参cls对应实参的id:%s" % id(cls))
obj = super().__new__(cls) #此处通过super() 调用父类即object的new 方法
print("创建的实例对象的id:%s" % id(obj))
return obj #将object 创建的实例对象返回,作为__init__接收的参数
class Child(Parent):
def __init__(self, name):
print("子类的__init__()被调用,其形参self对应实参的id:%s" % id(self))
self.name = name
print("父类的id:%s" % id(Parent))
print("子类的id:%s" % id(Child))
child = Child("Mike")
print("创建的实例对象的id:%s" % id(child))
打印输出结果如下
父类的id:2634116445304 #父类对象的id
子类的id:2634116450968 #子类对象的id
父类的__new__()被调用,其形参cls对应实参的id:2634116450968 #对应实例创建的第1步 打印语句1,new接收的是一个类对象,同子类的id
创建的实例对象的id:2634151784064 ##对应实例创建的第1步 打印语句2
子类的__init__()被调用,其形参self对应实参的id:2634151784064 #对应实例创建的第2步,接收的为第1步返回的实例对象
创建的实例对象的id:2634151784064 #__init__外的实例对象,3者的id一样
实例的销毁
作为高级语言,python系统会自动销毁不再需要的对象以释放内存。如需要执行额外的清理工作,可以在自定义的类对象中实现特殊方法__del__( )。
这样,当内存中的对象被销毁(垃圾回收)之前,会自动调用器对应的特殊方法__del__( )。
示例代码如下
class MyClass(object):
def __del__(self):
print("特殊方法__del__被调用")
mc = MyClass()
del mc
注意!!!
此处仅作为示例,自己编写的代码很少需要实现__del__ 代码,有些Python 新手会花时间实现,但却吃力不讨好,因为__del__ 很难用对。
__init__ , __new__ 和__del__&spm=1001.2101.3001.5002&articleId=108621253&d=1&t=3&u=06d20a8abbbd4f33839dc5520b169d91)

被折叠的 条评论
为什么被折叠?



