12 4月 2011

[Python] 取得Python object的reference count

在Python的世界裡,每個變數都是一個object,而且每個object會有一個reference count去記錄被reference幾次,一但這個值變0時,這個object才會真正被delete掉。



在Python的sys module裡,提供了一個API getrefcount()可以取得一個object的reference count是多少,回傳值是數字,而且回傳值應該會比你預期的值還要高,這是因為object在傳進getreference()時,reference count就會偷偷加一了。

看到下面的範例,a是一個Test的instance,reference count跟預期一樣是2(一個link到a,一個link到getrefcount的temporarily的變數),而b是一個list的instance,結果跟a一樣。

不過c跟d是一個string object,Python底層將c跟d link到同一個instance,所以在d='a'之後,c的reference count再加1。不過數字為何這麼地高,猜測應該是Python底層有自己去cache這些string object吧。
import sys

class Test:
    def __init__(self, v):
        self.v = v
a = Test(0)
print id(a), sys.getrefcount(a)
#>>> 19119440 2

b = list()
print id(b), sys.getrefcount(b)
#>>> 19135064 2

c = 'a'
print id(c), sys.getrefcount(c)
#>>> 18765728 18
d = 'a'
print id(c), sys.getrefcount(c)
#>>> 18765728 19
print id(d), sys.getrefcount(d)
#>>> 18765728 19

---
題外話,研究一下Python的source code,
在CPython裡,每個PyObject都有一個記reference count的變數,此變數為ob_refcnt。所以可以自己寫一個get reference count的function。寫在c/c++ code裡,然後用SWIG轉成python module,取得Python object正確的reference count。
int GetReferenceCount(PyObject *obj)
{
    return obj ?  obj->ob_refcnt : 0;
}

沒有留言: