和許多其它的高級語言一樣,Python使用了垃圾回收器來自動銷燬那些不再使用的對象。每個對象都有一個引用計數,當這個引用計數爲0時Python能夠安全地銷燬這個對象。
使用weakref模塊,你可以創建到對象的弱引用,Python在對象的引用計數爲0或只存在對象的弱引用時將回收這個對象。
一、 創建弱引用
你可以通過調用weakref模塊的ref(obj[,callback])來創建一個弱引用,obj是你想弱引用的對象,callback是一個可選的函數,當因沒有引用導致Python要銷燬這個對象時調用。回調函數callback要求單個參數(弱引用的對象)。
一旦你有了一個對象的弱引用,你就能通過調用弱引用來獲取被弱引用的對象。下面的例子創建了一個對socket對象的弱引用:
>>> from socket import *
>>> import weakref
>>> s=socket(AF_INET,SOCK_STREAM)
>>> ref=weakref.ref(s)
>>> s
<socket._socketobject instance at 007B4A94>
>>> ref
<weakref at 0x81195c; to 'instance' at 0x7b4a94>
>>> ref() #調用它來訪問被引用的對象
<socket.socketobject instance at 007B4A94>
一旦沒有了對這個對象的其它的引用,調用弱引用將返回None,因爲Python已經銷燬了這個對象。 注意:大部分的對象不能通過弱引用來訪問。
weakref模塊中的getweakrefcount(obj)和getweakrefs(obj)分別返回弱引用數和關於所給對象的引用列表。
弱引用對於創建對象(這些對象很費資源)的緩存是有用的。
二、創建代理對象
代理對象是弱引用對象,它們的行爲就像它們所引用的對象,這就便於你不必首先調用弱引用來訪問背後的對象。通過weakref模塊的proxy(obj[,callback])函數來創建代理對象。使用代理對象就如同使用對象本身一樣:
>>> from socket import*
>>> import weakref
>>> s=socket(AF_INET,SOCK_STREAM)
>>> ref=weakref.proxy(s)
>>> s
<socket._socketobject instance at 007E4874>
>>> ref
<socket._socketobject instance at 007E4874>
>>> ref.close() #對象的方法同樣工作
callback參數的目的和ref函數相同。在Python刪除了一個引用的對象之後,使用代理將會導致一個weakref.ReferenceError錯誤:
>>> def s
>>> ref
Traceback (most recent call last):
File "<stdin>", line 1, in ?
弱引用使用的機會不是很多,一般用來進行 cache 編程。我們可以使用 weakref.ref() 來創建一個弱引用。
>>>> import sys
>>> import weakref
>>> class Class1:
def test(self):
print "test..."
>>> o = Class1()
>>> sys.getrefcount(o)
2
>>> r = weakref.ref(o) # 創建一個弱引用
>>> sys.getrefcount(o) # 引用計數並沒有改變
2
>>> r
<weakref at 00D3B3F0; to 'instance' at 00D37A30> # 弱引用所指向的對象信息
>>> o2 = r() # 獲取弱引用所指向的對象
>>> o is o2
True
>>> sys.getrefcount(o)
3
>>> o = None
>>> o2 = None
>>> r # 當對象引用計數爲零時,弱引用失效。
<weakref at 00D3B3F0; dead>de>
weakref 還提供了一個 proxy():
import sys
import weakref
class Class1:
def test(self):
print "test"
def callback(self):
print "callback"
o = Class1()
p = weakref.proxy(o, callback)
p.test()
o = None