英文:
Why does getrefcount increase by 2 when put inside a function?
问题
考虑以下代码。
import sys
a = [1, 2, 3]
def foo(x):
print(sys.getrefcount(x))
foo(a) # 输出4 -- 但为什么?
当我们调用 foo(a)
以及执行 print(sys.getrefcount(x))
时,数组 [1, 2, 3]
被变量 a
、函数 foo
的参数 x
以及 sys.getrefcount
的参数所引用。我预期应该打印出3。我错过了什么?
英文:
Consider the following code.
import sys
a = [1, 2, 3]
def foo(x):
print(sys.getrefcount(x))
foo(a) # prints out 4 -- but why?
When we invoke foo(a)
and when print(sys.getrefcount(x))
executes, the array [1, 2, 3]
is referenced by a
, by the parameter x
of the function foo
and by the parameter of sys.getrefcount
. I expected 3 to be printed out. What have I missed?
答案1
得分: 2
<sub>声明:我远非CPython内部的专家。这个答案是我对CPython源代码的理解,可能不是完整的故事,也不适用于所有情况。</sub>
你所缺少的引用是局部变量x
,它与参数引用不同。
在内部,调用foo
是通过使用函数参数的元组调用PyObject_Call
来执行的。在这个元组中持有的强引用是在调用sys.getrefcount(x)
时添加的唯一引用。然而,调用foo
是不同的,因为在C代码中不会直接对参数进行操作,而是需要将它们作为本地变量提供,以便在后续的字节码执行期间可以访问。存储Python可访问的本地变量的结构保持对参数对象的自己的强引用。这就是为什么在调用Python函数时引用计数会第二次增加的原因。
英文:
<sub> Disclaimer: I am far from an expert in CPython internals. This answer is the best of my understanding of what's going on from having skimmed the CPython source code. It may not be the whole story, or applicable to all cases.</sub>
The reference you're missing is the local variable x
, which is different from the argument reference.
Internally, the call to foo
is carried out by invoking PyObject_Call
with a tuple of the function arguments. The strong reference held by that tuple is the one reference that gets added in the case of calling sys.getrefcount(x)
. However, calling foo
is different because the arguments aren't acted on directly in the C code but instead need to be made available as local variables that are accessible during the subsequent bytecode execution. The structure that stores the Python-accessible local variables keeps its own strong reference to the argument objects. Hence why the reference count gets incremented a second time when calling a Python function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论