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

3

我希望在一个类中使用ConfigParser,它需要从析构函数中调用,但是会发生奇怪的事情。

这是我的代码:

"""
function name is 
test  ok!
test1 failed!
test2 failed!
test3 failed!

test4
...  ok!

"""

def test3():
  pass

class Class1:
  def __del__(self):
    test3()

if __name__=="__main__":
  obj=Class1()

如果函数命名为test1test2或者test3,那么将会抛出异常,且无法通过try except捕获。

异常信息如下:

E:\tc.py
Exception TypeError: "'NoneType' object is not callable" in <bound method Class1.__del__ of <__main__.Class1 instance at 0x00C18F58>> ignored

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

2个回答

11

对象销毁的顺序是未定义的。这意味着在调用 obj.__del__() 时,如果它被调用的话,test3() 可能已经被销毁了,也可能没有。

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

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

在Python中,几乎从不覆盖__del__。您应该重新考虑自己的设计。参见How do I correctly clean up a Python object?


这是完美的答案。 我过去习惯在析构函数中保存工作,就像在C ++中一样。这在Python中是错误的,我收到了这个红框。 - weimingzhen
1
@weimingzhen:没错,Python的__del__更类似于Java的finalizers而非C++的析构函数。在现代Python中,使用with语句释放资源是正确的习惯用法(try-finally只是一个次要的选择)。 - NPE

4

在调用 obj.__del__() 的时候,你不能确定 test3 是否已经被销毁。如果需要保留它,请在 Class1.__init__() 中添加一个引用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接