self = None是做什么的?

Der*_*ang 24 python garbage-collection python-internals python-asyncio

我正在阅读传入asyncio包的源代码.请注意,在方法的最后,有一个self = None声明.它有什么作用?

def _run(self):
    try:
        self._callback(*self._args)
    except Exception as exc:
        msg = 'Exception in callback {}{!r}'.format(self._callback,
                                                    self._args)
        self._loop.call_exception_handler({
            'message': msg,
            'exception': exc,
            'handle': self,
        })
    self = None  # Needed to break cycles when an exception occurs.
Run Code Online (Sandbox Code Playgroud)

我认为它会删除实例,但以下测试不建议如此:

class K:
    def haha(self):
        self = None

a = K()
a.haha()
print(a) # a is still an instance
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 24

它只是清除本地引用self,确保如果发生异常,则传递给的引用self._loop.call_exception_handler()是唯一剩余的引用,并且没有创建任何循环.

这仍然是需要的,因为异常回溯引用了本地命名空间.当函数退出时,它将不会被清除,因为仍然存在对当地人的引用.

这在sys.exc_info()功能文档中记录,并带有警告:

警告:将回溯返回值分配给处理异常的函数中的局部变量将导致循环引用.这将阻止同一函数中的局部变量或回溯引用的任何内容被垃圾回收.由于大多数函数不需要访问回溯,因此最好的解决方案是使用类似的方法exctype, value = sys.exc_info()[:2]来仅提取异常类型和值.如果确实需要回溯,请确保在使用后删除它(最好用try ... finally语句完成)或调用exc_info()本身不处理异常的函数.

因为tulip处理程序构成了一个基本的框架类,所以代码通过self从本地名称空间中删除来处理回溯循环引用案例,因为它不能保证_callback或者call_exception_handler函数将清除它们的引用.

在CPython中,对象在引用计数降为0时被销毁,但是循环引用(在一个循环中引用自身的一系列对象)将永远不会看到它们的引用计数降为0.垃圾收集器确实尝试打破这样的循环但是它不能总是这么做或不够快.明确清除引用可避免创建周期.

例如,如果有__del__方法,垃圾收集器将不会中断循环,因为它不知道在这种情况下安全地打破循环的顺序.

即使没有__del__方法(框架类不应该假设不是这种情况),最好不要依赖垃圾收集器最终清除周期.

  • @satoru:也许,但至少`self-> call_exception_handler-> exc - > __ traceback __-> f_locals-> self`循环消失了. (6认同)