【问题标题】:Does accessing a list change its ref count?访问列表是否会更改其引用计数?
【发布时间】:2012-12-17 17:43:59
【问题描述】:

我正在处理的原始问题概述了here。我想问一个与原始问题相关的附加问题(关于 Python 引用计数)。

假设我有以下脚本:

from bitarray import bitarray
from array import array

list1=[bitarray('00011'), bitarray('00010'), bitarray('11011')]
list2=[array('i',[0,0,0,0]),array('i',[1,1,1,1]),array('i',[2,2,2,2])]

def calculate(l1,l2):
    result1=l1[0]&l1[1]&l1[2]
    result2=l2[0][0]+l2[1][1]+l2[2][2]
return result1, result2

print calculate(list1,list2)

当我调用calculate(list1,list2) 时,list1list2 或任一列表中的任何对象的引用计数是否会在某些时候发生变化

澄清一下:我并不是说在调用calculate(list1,list2) 之前和之后引用计数是否相同。我的意思是如果引用计数在执行calculate(list1,list2) 期间的任何时候发生变化。

【问题讨论】:

    标签: python refcounting


    【解决方案1】:

    list1list2 的引用计数不会改变,它们只是变量,因此是 locals() 命名空间中的字符串键。

    这两个变量指向的 Python 列表对象,是的,它们的引用计数在传递给函数时会发生变化。在调用函数期间,两个 new 变量引用那些列表(l1l2)增加计数,当函数返回时,这些变量被清除并且引用计数再次下降.

    calculate() 函数中,您正在访问这两个列表的项目(l1[0] 等)。项目访问可以使用对象的__getitem__方法;方法在访问时即时创建,并保存对实例和底层函数的引用。对于一个列表,它是对列表对象的另一个引用,并且另一个临时引用计数增加。一旦函数被调用并返回它的值,该方法就会再次被丢弃(没有任何东西引用它)并且列表的引用计数再次下降。

    正如 delnan 在 cmets 中正确指出的那样,对于列表订阅,BINARY_SUBSCR 操作码优化了访问(假设索引是整数),在特定情况下没有创建任何方法

    python 解释器在处理堆栈上的字节码和值时,一直在增加和减少引用计数。查看Python bytecode evaluation loop 并计算Py_INCREFPy_DECREF 的出现次数,以了解这种情况的常见程度。

    【讨论】:

    • +1 在calculate 内部调用__getitem__ 或准备调用(LOAD_FAST 0 (l1); LOAD_CONST 0; BINARY_SUBSCR) 期间,也可能有(甚至更短的)引用。
    • 我是否理解正确,即使result1=l1[0]&l1[1]&l1[2] 行也会修改相关对象的引用计数?
    • @anti666:是的,引用计数可以快速上升和下降。
    • Nitpick:由于类上发生了特殊的方法查找,并且索引有自己的操作码,l1[0] 等可能不会创建绑定的方法对象。尽管如此,他们仍然在堆栈上放置了一个临时引用。 (和往常一样,这都是 CPython 特有的。)
    • @delnan:BINARY_SUBSCR 在所有情况下都将使用__getitem__,但使用整数的列表访问除外。 :-) 特殊情况,见ceval.c
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 2012-01-27
    • 2010-10-07
    相关资源
    最近更新 更多