python弱引用使用介紹

和許多其它的高級語言一樣,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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章