无法在任何类的析构函数中调用函数。

12 浏览
0 Comments

无法在任何类的析构函数中调用函数。

我想在一个类中使用ConfigParser,它需要在析构函数中调用,但是会出现奇怪的情况。这是我的代码:

"""
函数名称是
test 通过!
test1 失败!
test2 失败!
test3 失败!
test4
... 通过!
"""
def test3():
  pass
class Class1:
  def __del__(self):
    test3()
if __name__=="__main__":
  obj=Class1()

如果函数被命名为`test1`、`test2`或`test3`,将会引发异常,而我无法通过`try except`来捕获它。追踪信息如下:

E:\tc.py
异常 TypeError: "'NoneType' object is not callable" 在 > 中被忽略

这太奇怪了!你能在你的系统中测试一下吗?或者是我做错了什么?

0
0 Comments

无法确定在调用obj.__del__()时,test3是否已被销毁。如果需要保留test3,请在Class1.__init__()中添加对它的引用。

这个问题的原因是无法在析构函数中调用函数。在Python中,当一个对象被销毁时,会自动调用其析构函数__del__()。然而,由于Python的垃圾回收机制使用的是引用计数,当对象的引用计数为0时,即没有任何变量引用该对象时,对象才会被销毁。因此,在obj.__del__()中调用test3函数时,test3可能已经被销毁了。

要解决这个问题,可以在Class1.__init__()中添加对test3的引用。这样,在obj.__del__()被调用时,test3仍然存在。具体的做法是在Class1.__init__()中将test3赋值给一个实例变量,例如self.test3 = test3。这样,在obj.__del__()中就可以通过self.test3()来调用test3函数了。

下面是修改后的代码示例:

class Class1:
    def __init__(self, test3):
        self.test3 = test3
    
    def __del__(self):
        self.test3()
    
def test3():
    print("test3 function")
obj = Class1(test3)

这样,无论何时调用obj.__del__(),都能正常调用test3()函数,而不会出现问题。

0
0 Comments

在Python中,对象被销毁的顺序是不确定的。这意味着在调用obj.__del__()时(如果调用的话),test3()可能已经被销毁或者尚未被销毁。

在Python文档的文档中有一个带有警告的红色框框:

警告 由于__del__()方法被调用的不确定性情况,如果在执行期间发生异常,这些异常将被忽略,并且会打印一个警告到sys.stderr。此外,当__del__()方法作为对删除模块的响应被调用时(例如,当程序执行完成时),__del__()方法引用的其他全局变量可能已经被删除或正在被销毁过程中(例如,导入机制关闭)。因此,__del__()方法应该尽量只做维护外部不变性所需的最小操作。从1.5版本开始,Python确保以单下划线开头的全局变量在其他全局变量被删除之前从其模块中删除;如果对这些全局变量没有其他引用,这可能有助于确保在调用__del__()方法时导入的模块仍然可用。

在Python中,几乎不需要重写__del__方法。你应该重新考虑你的设计。请参见如何正确清理Python对象?这个完美的答案。我过去在析构函数中保存工作,就像在C++中一样,这在Python中是错误的,我看到了这个红色框框。

没错,Python的__del__更类似于Java的finalizer而不是C++的析构函数。在现代Python中,使用with语句是释放资源的正确习惯用法(try-finally是次要的方法)。

0