• 类和对象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__ 方法创建一个类的新实例,然后根据需要修改新创建的实例再将其返回。

    1. #创建不可变类型 tuple 的子类
    2. class Newtest(tuple):
    3. #调用 __new__ 方法,改写子类在对象实例化时操作
    4. def __new__(cls, inputtuple):
    5. inputtuple = inputtuple + ('default element',)
    6. #返回 super().__new__(cls[, ...]),通过父类的 __new__ 方法创建修改后子类的新实例
    7. return super().__new__(cls, inputtuple)
    8. #调用子类创建实例,执行成功
    9. tuplex = (1,2,3)
    10. tupley = Newtest(tuplex)
    11. tupley
    12. (1, 2, 3, 'default element')

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

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

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

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

    1. #创建类的 __init__ 方法有返回值
    2. class Inittest():
    3. def __init__(self, name):
    4. self.name = name
    5. return self.name
    6. #构造实例对象时报错
    7. testx = Inittest('abc')
    8. Traceback (most recent call last):
    9. File "<input>", line 1, in <module>
    10. TypeError: __init__() should return None, not 'str'
    11. #创建父类
    12. class Inittest():
    13. def __init__(self, name):
    14. self.name = name
    15. #创建不带父类初始化的子类1
    16. class Initderived1(Inittest):
    17. def __init__(self, value):
    18. self.value = value
    19. #创建带父类初始化的子类2
    20. class Initderived2(Inittest):
    21. def __init__(self, name, value):
    22. super().__init__(name)
    23. self.value = value
    24. #子类1构建实例,调用父类初始化赋值变量失败
    25. test1 = Initderived1('abc')
    26. test1.name
    27. Traceback (most recent call last):
    28. File "<input>", line 1, in <module>
    29. AttributeError: 'Initderived1' object has no attribute 'name'
    30. #子类2构建实例,调用父类、子类初始化赋值变量成功
    31. test2 = Initderived2('wow','abc')
    32. test2.name
    33. 'wow'
    34. test2.value
    35. 'abc'

    3. __del__(self)

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

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

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

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

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

    1. #创建父类
    2. class Deltest():
    3. def __init__(self, name):
    4. self.name = name
    5. def __del__(self):
    6. print(f'调用父类 del 方法')
    7. #创建不带父类析构方法的子类
    8. class Delderived1(Deltest):
    9. def __del__(self):
    10. print('调用子类1 del 方法')
    11. #创建带父类析构方法的子类
    12. class Delderived2(Deltest):
    13. def __del__(self):
    14. super().__del__()
    15. print('调用子类2 del 方法')
    16. #构建实例对象失败,调用 __del__ 方法
    17. test1 = Deltest()
    18. 调用父类 del 方法
    19. Traceback (most recent call last):
    20. File "<input>", line 1, in <module>
    21. TypeError: __init__() missing 1 required positional argument: 'name'
    22. #调用不带父类析构方法的子类,没有执行父类 __del__ 方法
    23. test1 = Delderived1('test1')
    24. del test1
    25. 调用子类1 del 方法
    26. #调用带父类析构方法的子类,执行父类 __del__ 方法
    27. test2 = Delderived2('test2')
    28. del test2
    29. 调用父类 del 方法
    30. 调用子类2 del 方法
    31. #只有当垃圾回收机制回收这个对象时,才会调用 __dell__ 方法
    32. test31 = Deltest('test')
    33. test32 = test31
    34. test33 = test32
    35. del test31
    36. del test33
    37. del test32
    38. 调用父类 del 方法

  • 相关阅读:
    手写简易操作系统(九)--实现打印函数
    Java数据结构与算法(四)
    react源码中的协调与调度
    【Linux】21、软中断、网络小包、SYN FLOOD 攻击、sar tcpdump
    Kafka收发消息核心参数详解
    龟速乘 - a * b爆ll且模数很大时的计算方法
    孩子如何才能学好python
    简单的镜面反射
    【笔记】大话设计模式-11-13
    将折叠屏卖到5999元!但摩托罗拉razr 2022的看点不止性价比
  • 原文地址:https://blog.csdn.net/davidksatan/article/details/125552763