一、三个方法的作用和区别
1. 角色分工
创建对象完整流程: __new__() → 创建实例对象(分配内存) → 返回实例 ↓ __init__() → 初始化实例对象(设置属性) ↓ 对象生命周期 ↓ __del__() → 销毁实例对象(垃圾回收)
2. 方法对比
| | | | |
|---|
__new__ | | | | |
__init__ | __new__ | | | |
__del__ | | | | |
二、__new__ 方法详解
1. 基本语法
class MyClass: def __new__(cls, *args, **kwargs): """ cls: 要实例化的类 args, kwargs: 传递给构造函数的参数 必须返回实例对象(通常是父类的__new__结果) """ print(f"__new__ called with cls={cls}") # 调用父类的__new__创建实例 instance = super().__new__(cls) return instance
2. 完整示例
class Person: instance_count = 0 def __new__(cls, name, age): print("1. __new__: 创建对象实例") # 统计实例数量 Person.instance_count += 1 print(f"已创建第{Person.instance_count}个Person实例") # 必须调用父类的__new__来分配内存 instance = super().__new__(cls) # 可以在__new__中设置一些特殊属性 instance.created_at = "in __new__" return instance def __init__(self, name, age): print("2. __init__: 初始化对象属性") self.name = name self.age = age self.created_at = "in __init__" # 会覆盖__new__中的值# 使用p = Person("Alice", 25)print(f"姓名: {p.name}, 年龄: {p.age}")print(f"创建标记: {p.created_at}")print(f"总实例数: {Person.instance_count}")
输出:
1. __new__: 创建对象实例已创建第1个Person实例2. __init__: 初始化对象属性姓名: Alice, 年龄: 25创建标记: in __init__总实例数: 1
三、__init__ 方法详解
1. 基本用法
class Student: def __init__(self, name, score, gender="未知"): """ self: 实例对象本身 其他参数:初始化时传入的参数 """ self.name = name self.score = score self.gender = gender self._validate() # 可以在初始化时进行验证 def _validate(self): if self.score < 0 or self.score > 100: raise ValueError("分数必须在0-100之间") if not isinstance(self.name, str): raise TypeError("姓名必须是字符串")# 使用s1 = Student("张三", 85)s2 = Student("李四", 92, "男")print(f"{s1.name}的成绩是{s1.score}")print(f"{s2.name}的性别是{s2.gender}")
2. 带默认值和类型提示的__init__
from typing import Optional, Listclass Book: def __init__( self, title: str, author: str, price: float = 0.0, tags: Optional[List[str]] = None, **kwargs # 接收额外参数 ): self.title = title self.author = author self.price = price self.tags = tags if tags is not None else [] # 处理额外参数 for key, value in kwargs.items(): setattr(self, key, value) # 计算属性 self.discounted_price = price * 0.9 if price > 50 else price def display(self): print(f"《{self.title}》 - {self.author}") print(f"价格: ¥{self.price:.2f}") if self.tags: print(f"标签: {', '.join(self.tags)}")# 使用book = Book( title="Python编程", author="John Doe", price=89.9, tags=["编程", "Python", "计算机"], publisher="清华出版社" # 额外参数)book.display()print(f"出版社: {book.publisher}")print(f"折后价: ¥{book.discounted_price:.2f}")
四、__del__ 方法详解
1. 基本用法
class Resource: def __init__(self, name): self.name = name print(f"资源 '{self.name}' 已创建") def __del__(self): print(f"资源 '{self.name}' 正在被销毁") # 在这里进行资源清理 self.cleanup() def cleanup(self): print(f"清理资源 '{self.name}' 的相关数据") def use(self): print(f"使用资源 '{self.name}'")# 使用def test_resource(): print("开始测试资源") res = Resource("数据库连接") res.use() print("测试结束") # 函数结束时,res超出作用域,可能触发__del__test_resource()print("测试函数已结束")
2. 手动触发垃圾回收
import gcclass FileHandler: def __init__(self, filename): self.filename = filename self.file = open(filename, 'w') print(f"文件 '{filename}' 已打开") def write(self, content): self.file.write(content) print(f"已写入内容到 '{self.filename}'") def __del__(self): print(f"关闭文件 '{self.filename}'") if hasattr(self, 'file') and not self.file.closed: self.file.close() def close(self): """手动关闭文件""" if hasattr(self, 'file') and not self.file.closed: self.file.close() print(f"手动关闭了文件 '{self.filename}'")# 使用print("=== 示例1: 自动回收 ===")fh1 = FileHandler("test1.txt")fh1.write("Hello World")# 删除引用del fh1print("\n=== 示例2: 手动回收 ===")fh2 = FileHandler("test2.txt")fh2.write("Python")# 先手动关闭fh2.close()# 再删除del fh2print("\n=== 示例3: 强制垃圾回收 ===")gc.collect() # 强制进行垃圾回收
注意:__del__ 的调用时机由Python的垃圾回收器决定,不保证立即执行!
五、重要注意事项
1. __del__ 的局限性
class ProblematicClass: def __init__(self, name): self.name = name self.parent = None def set_parent(self, parent): self.parent = parent def __del__(self): print(f"删除 {self.name}")# 循环引用问题print("=== 循环引用示例 ===")a = ProblematicClass("A")b = ProblematicClass("B")a.set_parent(b)b.set_parent(a)# 删除引用del adel bprint("手动触发垃圾回收...")import gcprint(f"垃圾对象: {gc.collect()}")# 解决方案:使用 weakrefimport weakrefclass SafeClass: def __init__(self, name): self.name = name self._parent = None def set_parent(self, parent): # 使用弱引用避免循环引用 self._parent = weakref.ref(parent) @property def parent(self): return self._parent() if self._parent else None def __del__(self): print(f"安全删除 {self.name}")
2. __new__ 和 __init__ 的协作
class CollaborativeClass: def __new__(cls, value): print(f"__new__: 接收到 value={value}") # 可以修改参数 if isinstance(value, str): value = value.upper() # 创建实例 instance = super().__new__(cls) # 可以在__new__中存储信息供__init__使用 instance._original_value = value return instance def __init__(self, value): print(f"__init__: 接收到 value={value}") # __init__接收的是原始参数 self.value = self._original_value # 使用__new__处理后的值 print(f"最终值: {self.value}")# 使用obj = CollaborativeClass("hello")
六、总结
1.__new__ 的使用场景:
2.__init__ 的使用场景:
初始化实例属性
参数验证
计算派生属性
建立对象间的关系
3.__del__的使用场景:
资源清理(文件、网络连接等)
日志记录
注意:避免在 __del__ 中做耗时操作
4.设计建议: