考虑以下代码。
import sys
a = [1, 2, 3]
def foo(x):
print(sys.getrefcount(x))
foo(a) # prints out 4 -- but why?
当我们调用
foo(a)
并且当print(sys.getrefcount(x))
执行时,数组[1, 2, 3]
被a
、函数x
的参数foo
和sys.getrefcount
的参数引用。我希望打印出 3。我错过了什么?
免责声明:我远不是 CPython 内部专家。这个答案是我对浏览 CPython 源代码所发生的事情的最好理解。它可能不是全部,或适用于所有情况。
您缺少的引用是局部变量
x
,它与参数引用不同。
在内部,对
foo
的调用是通过使用函数参数的元组调用PyObject_Call
来执行的。该元组持有的 strong reference 是在调用 sys.getrefcount(x)
的情况下添加的一个引用。然而,调用 foo
是不同的,因为参数不是直接在 C 代码中起作用,而是需要作为局部变量可用,以便在后续字节码执行期间访问。存储 Python 可访问的局部变量的结构保留了它自己对参数对象的强引用。因此,为什么在调用 Python 函数时引用计数会第二次增加。