Python 中的析构函数


构造函数 当对象被销毁时会调用析构函数。在 Python 中,不像 C++ 那样需要析构函数,因为 Python 有一个垃圾收集器,可以自动处理内存管理。 del ()方法在Python 中被称为析构函数方法。当对该对象的所有引用都已被删除时(即当对象被垃圾收集时),将调用它。 析构函数声明的语法:

def __del__(self):
  # body of destructor

注意:当对象失去引用或程序结束时,对对象的引用也会被删除。 示例 1:这是析构函数的简单示例。通过使用 del 关键字,我们删除了对象“obj”的所有引用,因此自动调用析构函数。

  • Python3
# Python program to illustrate destructor
class Employee:

    # Initializing
    def __init__(self):
        print('Employee created.')

    # Deleting (Calling destructor)
    def __del__(self):
        print('Destructor called, Employee deleted.')

obj = Employee()
del obj

输出

Employee created.
Destructor called, Employee deleted.

注意:析构函数在程序结束后或当所有对对象的引用被删除时(即引用计数变为零时)调用,而不是在对象超出范围时调用。 例2:本例对上述注释进行解释。在这里,请注意析构函数是在打印“Program End...”之后调用的。

# Python program to illustrate destructor

class Employee:

    # Initializing
    def __init__(self):
        print('Employee created')

    # Calling destructor
    def __del__(self):
        print("Destructor called")

def Create_obj():
    print('Making Object...')
    obj = Employee()
    print('function end...')
    return obj

print('Calling Create_obj() function...')
obj = Create_obj()
print('Program End...')

输出

Calling Create_obj() function...
Making Object...
Employee created
function end...
Program End...

示例 3:现在,考虑以下示例:

  • Python3
# 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() 方法为类定义析构函数。当对象即将被垃圾收集器销毁时,会自动调用此方法。以下是如何在递归函数中使用析构函数的示例:

  • Python
class RecursiveFunction:
    def __init__(self, n):
        self.n = n
        print("Recursive function initialized with n =", n)

    def run(self, n=None):
        if n is None:
            n = self.n
        if n <= 0:
            return
        print("Running recursive function with n =", n)
        self.run(n-1)

    def __del__(self):
        print("Recursive function object destroyed")

# Create an object of the class
obj = RecursiveFunction(5)

# Call the recursive function
obj.run()

# Destroy the object
del obj

输出

('Recursive function initialized with n =', 5)
('Running recursive function with n =', 5)
('Running recursive function with n =', 4)
('Running recursive function with n =', 3)
('Running recursive function with n =', 2)
('Running recursive function with n =', 1)
Recursive function object destroyed

在此示例中,我们定义了一个类 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的一个重要特性,可以帮助确保对象被正确清理并且资源不被浪费。它们易于使用,可用于强制执行封装和其他面向对象设计的原则。


原文链接:codingdict.net