类和对象7:构造和析构方法

目录

1. __new__(cls[, ...])

2. __init__(self[, ...])

3. __del__(self)


1. __new__(cls[, ...])

__new__ 是对象实例化时调用的第一个方法,调用以创建一个 cls 类的新实例;

__new__ 将所请求实例所属的类作为第一个参数,即 cls 参数,其他参数会直接传给 __init__ 方法;

__new__ 通常不需要重写,默认执行即可;如果重写,一般用于允许不可变类型的子类 (例如 int, str 或 tuple) 定制实例创建过程,也常会在自定义元类中被重载以便定制类创建过程;

典型的实现会附带适宜的参数使用 super().__new__(cls[, ...]),通过父类的 __new__ 方法创建一个类的新实例,然后根据需要修改新创建的实例再将其返回。

#创建不可变类型 tuple 的子类
class Newtest(tuple):

#调用 __new__ 方法,改写子类在对象实例化时操作
    def __new__(cls, inputtuple):
        inputtuple = inputtuple + ('default element',)
#返回 super().__new__(cls[, ...]),通过父类的 __new__ 方法创建修改后子类的新实例
        return super().__new__(cls, inputtuple)

#调用子类创建实例,执行成功
tuplex = (1,2,3)
tupley = Newtest(tuplex)
tupley
(1, 2, 3, 'default element')

2. __init__(self[, ...])

在实例(通过 __new__ 方法)被创建之后,返回调用者之前调用,其参数与传递给类构造器表达式的参数相同,相当于其他面向对象编程语言的构造方法;

实例对象由 __new__ 创建、__init__ 定制, 两个方法协作完成实例对象的构造,__init__ 返回值只能为 None,否则会在构造实例对象时报错;

如一个父类有重写的 __init__ 方法,其派生的子类如果也有重写 __init__ 方法,则需要在子类的 __init__ 方法中确保实例对象构造中父类部分的正确初始化,如添加 super().__init__([args...]) 代码段。

#创建类的 __init__ 方法有返回值
class Inittest():
    def __init__(self, name):
        self.name = name
        return self.name

#构造实例对象时报错
testx = Inittest('abc')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: __init__() should return None, not 'str'

#创建父类
class Inittest():
    def __init__(self, name):
        self.name = name
#创建不带父类初始化的子类1
class Initderived1(Inittest):
    def __init__(self, value):
        self.value = value
#创建带父类初始化的子类2
class Initderived2(Inittest):
    def __init__(self, name, value):
        super().__init__(name)
        self.value = value

#子类1构建实例,调用父类初始化赋值变量失败
test1 = Initderived1('abc')
test1.name
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Initderived1' object has no attribute 'name'

#子类2构建实例,调用父类、子类初始化赋值变量成功
test2 = Initderived2('wow','abc')
test2.name
'wow'
test2.value
'abc'

3. __del__(self)

__del__ 方法在实例将被销毁时调用,相当于其他面向对象编程语言的析构方法;

del object 不等于自动调用 object.__del__(),只有当垃圾回收机制回收这个对象时,才会调用 __dell__ 方法;即需要清除所有指向 object 实际地址的所有对象,开启垃圾回收机制, __dell__ 方法才开始执行;

当构建实例对象失败时,也会自动调用 __del__ 方法;

如一个父类有重写的 __del__ 方法,其派生的子类如果也有重写 __del__ 方法,则需要在子类的 __del__ 方法中确保删除实例对象时对其父类部分的正确析构,如添加 super().__del__(self) 代码段。

__del__ 方法可以(但不推荐!)通过创建一个该实例的新引用来推迟其销毁,这被称为对象重生。__del__() 是否会在重生的对象将被销毁时再次被调用是由具体实现决定的,当前的 CPython 实现只会调用一次。

#创建父类
class Deltest():
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f'调用父类 del 方法')
#创建不带父类析构方法的子类
class Delderived1(Deltest):
    def __del__(self):
        print('调用子类1 del 方法')
#创建带父类析构方法的子类
class Delderived2(Deltest):
    def __del__(self):
        super().__del__()
        print('调用子类2 del 方法')

#构建实例对象失败,调用 __del__ 方法 
test1 = Deltest()
调用父类 del 方法
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'name'

#调用不带父类析构方法的子类,没有执行父类 __del__ 方法
test1 = Delderived1('test1')
del test1
调用子类1 del 方法
#调用带父类析构方法的子类,执行父类 __del__ 方法
test2 = Delderived2('test2')
del test2
调用父类 del 方法
调用子类2 del 方法

#只有当垃圾回收机制回收这个对象时,才会调用 __dell__ 方法
test31 = Deltest('test')
test32 = test31
test33 = test32
del test31
del test33
del test32
调用父类 del 方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

燃烧的火鸟啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值