为何每次评估列表时都会触发PyList_Append调用?
问题原因分析
当你在REPL中输入a并回车时,REPL会调用sys.displayhook展示列表对象的结果,而展示过程会触发repr(a)的执行。为了避免循环引用导致的无限递归,CPython在PyObject_Repr(所有对象repr的入口函数)中会先调用Py_ReprEnter函数,该函数会维护一个线程本地的列表repr_stack,用于记录当前正在生成repr的对象:
- 生成列表
a的repr时,Py_ReprEnter会把a追加到repr_stack; - 遍历列表元素时,对其中的字典对象调用
PyObject_Repr,此时Py_ReprEnter会再次调用PyList_Append,把这个字典对象追加到repr_stack中——这就是你每次输入a都会触发断点的原因。
换句话说,你看到的PyList_Append调用并非来自列表a本身的修改,而是CPython内部为了处理repr时的循环引用检测,将字典临时加入到了内部维护的repr_stack列表中。当repr生成完成后,Py_ReprLeave会把对象从repr_stack中弹出,这个列表的内容会在每次repr结束后恢复。
内容的提问来源于stack exchange,提问作者Amir reza Riahi
相关产品推荐
相关产品推荐

