Python 析构函数

在Python中,析构函数(Destructors)是用于释放对象所占用资源的特殊方法。它是一个以双下划线开头和结尾的方法,命名为 del。析构函数在对象的生命周期即将结束时自动调用,通常在对象不再被引用且将要被垃圾回收时执行。

析构函数的主要作用是执行一些清理操作,例如关闭文件、释放网络连接、释放内存等。当不再需要对象时,Python的垃圾回收机制会自动调用析构函数,以确保对象占用的资源被正确释放,从而避免内存泄漏和资源泄漏问题。

析构函数声明的语法:

def __del__(self):
  # body of destructor

注意:当对象失去引用或程序结束时,对对象的引用也会被删除。 

示例 1:这是析构函数的简单示例。通过使用 del 关键字,我们删除了对象“obj”的所有引用,因此自动调用析构函数。

# Python程序演示析构函数
class Employee:

	# 初始化
	def __init__(self):
		print('创建了员工对象.')

	# 删除(调用析构函数)
	def __del__(self):
		print('调用了析构函数,删除了员工对象.')

obj = Employee()
del obj

输出:

创建了员工对象.
调用了析构函数,删除了员工对象.

注意:析构函数在程序结束后或当所有对对象的引用都被删除时(即引用计数变为零时)调用,而不是在对象超出范围时调用。

例2:本例对上述注释进行解释。在这里,请注意析构函数是在打印“程序结束…”之后调用的。

# Python程序演示析构函数

class Employee:

	# 初始化
	def __init__(self):
		print('创建了员工对象')

	# 调用析构函数
	def __del__(self):
		print("析构函数被调用")

def Create_obj():
	print('正在创建对象...')
	obj = Employee()
	print('函数结束...')
	return obj

print('正在调用Create_obj()函数...')
obj = Create_obj()
print('程序结束...')

输出:

正在调用Create_obj()函数...
正在创建对象...
创建了员工对象
函数结束...
程序结束...
析构函数被调用

示例 3:

# Python program to illustrate destructor

class A:
	def __init__(self, bb):
		self.b = bb

class B:
	def __init__(self):
		self.a = A(self)
	def __del__(self):
		print("die")

def fun():
	b = B()

fun()

输出:

die

在此示例中,当调用函数 fun() 时,它会创建类 B 的一个实例,该实例将自身传递给类 A,然后类 A 设置对类 B 的引用并导致循环引用

通常,用于检测这些类型的循环引用的 Python 垃圾收集器会将其删除,但在本示例中,使用自定义析构函数将此项标记为“不可收集”。 

简单地说,它不知道销毁对象的顺序,因此它会留下它们。因此,如果您的实例涉及循环引用,那么只要应用程序运行,它们就会驻留在内存中。

注意:示例 3 中提到的问题在较新版本的 python 中已得到解决,但在 < 3.4 版本中仍然存在。

示例:递归中的销毁

在 Python 中,您可以使用 __del__() 方法为类定义析构函数。当对象即将被垃圾收集器销毁时,会自动调用此方法。以下是如何在递归函数中使用析构函数的示例:

class RecursiveFunction:
	def __init__(self, n):
		self.n = n
		print("使用 n =", n + " 初始化递归函数")

	def run(self, n=None):
		if n is None:
			n = self.n
		if n <= 0:
			return
		print("使用 n =", n + " 运行递归函数")
		self.run(n-1)

	def __del__(self):
		print("销毁递归函数对象")

# 创建一个类的对象
obj = RecursiveFunction(5)

# 调用递归函数
obj.run()

# 销毁对象
del obj

输出:

('使用 n = 初始化递归函数', 5) 
('使用 n = 运行递归函数', 5) 
('使用 n = 运行递归函数', 4) 
('使用 n = 运行递归函数', 3) 
('使用 n = 运行递归函数', 2) 
('使用 n = 运行递归函数', 1)
销毁递归函数对象

在此示例中,我们定义了一个类 RecursiveFunction,其 __init__() 方法接受参数 n。该参数存储为对象的属性。

我们还定义了一个 run() 方法,它接受一个可选参数 n。如果未提供 n,则默认为 self.n 的值。run() 方法运行一个递归函数,该函数将消息打印到控制台并使用 n-1 调用自身。

我们使用 __del__() 方法定义一个析构函数,该方法只是将一条消息打印到控制台,指示该对象已被销毁。

我们创建一个 RecursiveFunction 类的对象,其中 n 设置为 5,并调用 run() 方法。这将运行递归函数,为每次调用将消息打印到控制台。

最后,我们使用 del 语句销毁该对象。这会触发析构函数,该析构函数会向控制台打印一条消息,指示该对象已被销毁。

请注意,在本例中,递归函数将继续运行,直到 n 达到 0。当 n 为 0 时,函数将返回,并且对象将被垃圾收集器销毁。然后析构函数将被自动调用。

在 Python 中使用析构函数的优点:

  • 自动清理:当不再需要对象时,析构函数可以自动清理对象所使用的资源。这在资源有限或清理失败可能导致内存泄漏或其他问题的情况下特别有用。
  • 一致的行为:析构函数确保对象被正确清理,无论它如何使用或何时被销毁。这有助于确保一致的行为,并有助于防止错误和其他问题。
  • 易于使用:析构函数在 Python 中很容易实现,并且可以使用 __del__() 方法进行定义。
  • 支持面向对象编程:析构函数是面向对象编程的一个重要特征,可用于强制封装和其他面向对象设计原则。
  • 有助于调试:析构函数对于调试很有用,因为它们可用于跟踪对象的生命周期并确定对象何时被销毁。

总的来说,析构函数是Python的一个重要特性,可以帮助确保对象被正确清理并且资源不被浪费。它们易于使用,可用于强制执行封装和其他面向对象设计的原则。

原创文章,作者:jkhxw,如若转载,请注明出处:https://www.jkhxw.com/python-destructors/

(0)
上一篇 2023年9月26日 下午11:33
下一篇 2023年9月27日 上午6:59

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注