亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Python 弱引用 學(xué)習(xí)

philadelphia / 1159人閱讀

摘要:引用計(jì)數(shù)會(huì)記錄給定對(duì)象的引用個(gè)數(shù),并在引用個(gè)數(shù)為零時(shí)收集該對(duì)象。在對(duì)象群組內(nèi)部使用弱引用即不會(huì)在引用計(jì)數(shù)中被計(jì)數(shù)的引用有時(shí)能避免出現(xiàn)引用環(huán),因此弱引用可用于解決循環(huán)引用的問題。

參考
1.weakref – Garbage-collectable references to objects
2.Python弱引用介紹

和許多其它的高級(jí)語言一樣,Python使用了垃圾回收器來自動(dòng)銷毀那些不再使用的對(duì)象。每個(gè)對(duì)象都有一個(gè)引用計(jì)數(shù),當(dāng)這個(gè)引用計(jì)數(shù)為0時(shí)Python能夠安全地銷毀這個(gè)對(duì)象。

引用計(jì)數(shù)會(huì)記錄給定對(duì)象的引用個(gè)數(shù),并在引用個(gè)數(shù)為零時(shí)收集該對(duì)象。由于一次僅能有一個(gè)對(duì)象被回收,引用計(jì)數(shù)無法回收循環(huán)引用的對(duì)象。

一組相互引用的對(duì)象若沒有被其它對(duì)象直接引用,并且不可訪問,則會(huì)永久存活下來。一個(gè)應(yīng)用程序如果持續(xù)地產(chǎn)生這種不可訪問的對(duì)象群組,就會(huì)發(fā)生內(nèi)存泄漏。

在對(duì)象群組內(nèi)部使用弱引用(即不會(huì)在引用計(jì)數(shù)中被計(jì)數(shù)的引用)有時(shí)能避免出現(xiàn)引用環(huán),因此弱引用可用于解決循環(huán)引用的問題。

在計(jì)算機(jī)程序設(shè)計(jì)中,弱引用,與強(qiáng)引用相對(duì),是指不能確保其引用的對(duì)象不會(huì)被垃圾回收器回收的引用。一個(gè)對(duì)象若只被弱引用所引用,則可能在任何時(shí)刻被回收。弱引用的主要作用就是減少循環(huán)引用,減少內(nèi)存中不必要的對(duì)象存在的數(shù)量。

使用weakref模塊,你可以創(chuàng)建到對(duì)象的弱引用,Python在對(duì)象的引用計(jì)數(shù)為0或只存在對(duì)象的弱引用時(shí)將回收這個(gè)對(duì)象。

創(chuàng)建弱引用

你可以通過調(diào)用weakref模塊的ref(obj[,callback])來創(chuàng)建一個(gè)弱引用,obj是你想弱引用的對(duì)象,callback是一個(gè)可選的函數(shù),當(dāng)因沒有引用導(dǎo)致Python要銷毀這個(gè)對(duì)象時(shí)調(diào)用?;卣{(diào)函數(shù)callback要求單個(gè)參數(shù)(弱引用的對(duì)象)。

一旦你有了一個(gè)對(duì)象的弱引用,你就能通過調(diào)用弱引用來獲取被弱引用的對(duì)象。

>>>> import sys
>>> import weakref
>>> class Man:
  def __init__(self,name):
    print self.name = name
    
>>> o = Man("Jim")
>>> sys.getrefcount(o)   
2
>>> r = weakref.ref(o) # 創(chuàng)建一個(gè)弱引用
>>> sys.getrefcount(o) # 引用計(jì)數(shù)并沒有改變
2
>>> r
 # 弱引用所指向的對(duì)象信息
>>> o2 = r() # 獲取弱引用所指向的對(duì)象
>>> o is o2
True
>>> sys.getrefcount(o)
3
>>> o = None
>>> o2 = None
>>> r # 當(dāng)對(duì)象引用計(jì)數(shù)為零時(shí),弱引用失效。
de>

上面的代碼中,我們使用sys包中的getrefcount()來查看某個(gè)對(duì)象的引用計(jì)數(shù)。需要注意的是,當(dāng)使用某個(gè)引用作為參數(shù),傳遞給getrefcount()時(shí),參數(shù)實(shí)際上創(chuàng)建了一個(gè)臨時(shí)的引用。因此,getrefcount()所得到的結(jié)果,會(huì)比期望的多1。

一旦沒有了對(duì)這個(gè)對(duì)象的其它的引用,調(diào)用弱引用將返回None,因?yàn)镻ython已經(jīng)銷毀了這個(gè)對(duì)象。 注意:大部分的對(duì)象不能通過弱引用來訪問。

weakref模塊中的getweakrefcount(obj)和getweakrefs(obj)分別返回弱引用數(shù)和關(guān)于所給對(duì)象的引用列表。

弱引用對(duì)于創(chuàng)建對(duì)象(這些對(duì)象很費(fèi)資源)的緩存是有用的。

創(chuàng)建代理對(duì)象

代理對(duì)象是弱引用對(duì)象,它們的行為就像它們所引用的對(duì)象,這就便于你不必首先調(diào)用弱引用來訪問背后的對(duì)象。通過weakref模塊的proxy(obj[,callback])函數(shù)來創(chuàng)建代理對(duì)象。使用代理對(duì)象就如同使用對(duì)象本身一樣:

import weakref

class Man:
    def __init__(self, name):
        self.name = name
    def test(self):
        print "this is a test!"

def callback(self):
    print "callback"
    
o = Man("Jim")
p = weakref.proxy(o, callback)
p.test()
o=None
p.test()

callback參數(shù)的作用和ref函數(shù)中callback一樣。在Python刪除了一個(gè)引用的對(duì)象之后,使用代理將會(huì)導(dǎo)致一個(gè)weakref.ReferenceError錯(cuò)誤。

循環(huán)引用

前面說過,使用弱引用,可以解決循環(huán)引用不能被垃圾回收的問題。
首先我們看下常規(guī)的循環(huán)引用,先創(chuàng)建一個(gè)簡單的Graph類,然后創(chuàng)建三個(gè)Graph實(shí)例:

# -*- coding:utf-8 -*-
import weakref
import gc
from pprint import pprint


class Graph(object):
    def __init__(self, name):
        self.name = name
        self.other = None

    def set_next(self, other):
        print "%s.set_next(%r)" % (self.name, other)
        self.other = other

    def all_nodes(self):
        yield self
        n = self.other
        while n and n.name !=self.name:
            yield n
            n = n.other
        if n is self:
            yield n
        return

    def __str__(self):
        return "->".join(n.name for n in self.all_nodes())

    def __repr__(self):
        return "<%s at 0x%x name=%s>" % (self.__class__.__name__, id(self), self.name)

    def __del__(self):
        print "(Deleting %s)" % self.name

def collect_and_show_garbage():
    print "Collecting..."
    n = gc.collect()
    print "unreachable objects:", n
    print "garbage:",
    pprint(gc.garbage)


def demo(graph_factory):
    print "Set up graph:"
    one = graph_factory("one")
    two = graph_factory("two")
    three = graph_factory("three")
    one.set_next(two)
    two.set_next(three)
    three.set_next(one)

    print
    print "Graph:"
    print str(one)
    collect_and_show_garbage()

    print
    three = None
    two = None
    print "After 2 references removed"
    print str(one)
    collect_and_show_garbage()

    print
    print "removeing last reference"
    one = None
    collect_and_show_garbage()


gc.set_debug(gc.DEBUG_LEAK)
print "Setting up the cycle"
print 
demo(Graph)
print
print "breaking the cycle and cleaning up garbage"
print
gc.garbage[0].set_next(None)
while gc.garbage:
    del gc.garbage[0]
print collect_and_show_garbage()

這里使用了python的gc庫的幾個(gè)方法, 解釋如下:

gc.collect() 收集垃圾

gc.garbage 獲取垃圾列表

gc.set_debug(gc.DBEUG_LEAK) 打印無法看到的對(duì)象信息

運(yùn)行結(jié)果如下:

Setting up the cycle

Set up graph:
one.set_next()
two.set_next()
three.set_next()

Graph:
one->two->three->one
Collecting...
unreachable objects:g 0
garbage:[]

After 2 references removed
one->two->three->one
Collecting...
unreachable objects: 0
garbage:[]

removeing last reference
Collecting...
unreachable objects: 6
garbage:[,
 ,
 ,
 {"name": "one", "other": },
 {"name": "two", "other": },
 {"name": "three", "other": }]

breaking the cycle and cleaning up garbage

one.set_next(None)
(Deleting two)
(Deleting three)
(Deleting one)
Collecting...
unreachable objects: 0
garbage:[]
None
[Finished in 0.4s]c: uncollectable 
gc: uncollectable 
gc: uncollectable 
gc: uncollectable 
gc: uncollectable 
gc: uncollectable 

從結(jié)果中我們可以看出,即使我們刪除了Graph實(shí)例的本地引用,它依然存在垃圾列表中,不能回收。
接下來創(chuàng)建使弱引用的WeakGraph類:

class WeakGraph(Graph):
    def set_next(self, other):
        if other is not None:
            if self in other.all_nodes():
                other = weakref.proxy(other)
        super(WeakGraph, self).set_next(other)
        return
demo(WeakGraph)

結(jié)果如下:

Setting up the cycle

Set up graph:
one.set_next()
two.set_next()
three.set_next()

Graph:
one->two->three
Collecting...
unreachable objects:Traceback (most recent call last):
  File "D:appsplatformdemodemo.py", line 87, in 
    gc.garbage[0].set_next(None)
IndexError: list index out of range
 0
garbage:[]

After 2 references removed
one->two->three
Collecting...
unreachable objects: 0
garbage:[]

removeing last reference
(Deleting one)
(Deleting two)
(Deleting three)
Collecting...
unreachable objects: 0
garbage:[]

breaking the cycle and cleaning up garbage

[Finished in 0.4s with exit code 1]

上面的類中,使用代理來指示已看到的對(duì)象,隨著demo()刪除了對(duì)象的所有本地引用,循環(huán)會(huì)斷開,這樣垃圾回收期就可以將這些對(duì)象刪除。

因此我們我們?cè)趯?shí)際工作中如果需要用到循環(huán)引用的話,盡量采用弱引用來實(shí)現(xiàn)。

緩存對(duì)象

refproxy都只可用與維護(hù)單個(gè)對(duì)象的弱引用,如果想同時(shí)創(chuàng)建多個(gè)對(duì)象的弱引用咋辦?這時(shí)可以使用WeakKeyDictionaryWeakValueDictionary來實(shí)現(xiàn)。

WeakValueDictionary類,顧名思義,本質(zhì)上還是個(gè)字典類型,只是它的值類型是弱引用。當(dāng)這些值引用的對(duì)象不再被其他非弱引用對(duì)象引用時(shí),那么這些引用的對(duì)象就可以通過垃圾回收器進(jìn)行回收。
下面的例子說明了常規(guī)字典與WeakValueDictionary的區(qū)別。

# -*- coding:utf-8 -*-
import weakref
import gc
from pprint import pprint

gc.set_debug(gc.DEBUG_LEAK)


class Man(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "" % self.name

    def __del__(self):
        print "deleting %s" % self


def demo(cache_factory):
    all_refs = {}
    print "cache type:", cache_factory
    cache = cache_factory()
    for name in ["Jim", "Tom", "Green"]:
        man = Man(name)
        cache[name] = man
        all_refs[name] = man
        del man
    print "all_refs=",
    pprint(all_refs)
    print
    print "before, cache contains:", cache.keys()
    for name, value in cache.items():
        print "%s = %s" % (name, value)
    print "
cleanup"
    del all_refs
    gc.collect()

    print
    print "after, cache contains:", cache.keys()
    for name, value in cache.items():
        print "%s = %s" % (name, value)
    print "demo returning"
    return

demo(dict)
print

demo(weakref.WeakValueDictionary)

結(jié)果如下所示:

cache type: 
all_refs={"Green": , "Jim": , "Tom": }

before, cache contains: ["Jim", "Green", "Tom"]
Jim = 
Green = 
Tom = 

cleanup

after, cache contains: ["Jim", "Green", "Tom"]
Jim = 
Green = 
Tom = 
demo returning
deleting 
deleting 
deleting 

cache type: weakref.WeakValueDictionary
all_refs={"Green": , "Jim": , "Tom": }

before, cache contains: ["Jim", "Green", "Tom"]
Jim = 
Green = 
Tom = 

cleanup
deleting 
deleting 

after, cache contains: []
demo returning

[Finished in 0.3s]

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/37994.html

相關(guān)文章

  • Python基礎(chǔ)系列:初識(shí)python引用計(jì)數(shù)與引用

    摘要:第一次初始化對(duì)象,并且用變量來引用,所以這里的引用計(jì)數(shù)就為。接下來通過創(chuàng)建一個(gè)弱引用,通過打印引用計(jì)數(shù)后,發(fā)現(xiàn)計(jì)數(shù)并沒有改變。由于一次僅能有一個(gè)對(duì)象被回收,引用計(jì)數(shù)無法回收循環(huán)引用的對(duì)象。所以弱引用很適合處理這種循環(huán)引用的場景。 寫在前邊: 之前的socket系列就告一段落,主要是對(duì)自己所學(xué)做一個(gè)總結(jié)與記錄。 接下來我打算基于libevent寫一個(gè)支持并發(fā)的HTTP服務(wù)器。因?yàn)橹皩W(xué)習(xí)...

    robin 評(píng)論0 收藏0
  • Python學(xué)習(xí)之路27-對(duì)象引用、可變性和垃圾回收

    摘要:函數(shù)的參數(shù)作為引用時(shí)唯一支持的參數(shù)傳遞模式是共享傳參,它指函數(shù)的形參獲得實(shí)參中各個(gè)引用的副本,即形參是實(shí)參的別名。而在上面這個(gè)例子中,類的屬性實(shí)際上是形參所指向的對(duì)象所指對(duì)象,的別名。 《流暢的Python》筆記本篇是面向?qū)ο髴T用方法的第一篇,一共六篇。本篇主要是一些概念性的討論,內(nèi)容有:Python中的變量,對(duì)象標(biāo)識(shí),值,別名,元組的某些特性,深淺復(fù)制,引用,函數(shù)參數(shù),垃圾回收,de...

    Batkid 評(píng)論0 收藏0
  • Python中的對(duì)象引用、可變性和垃圾回收

    摘要:一對(duì)象引用基礎(chǔ)知識(shí)變量是標(biāo)注而不是容器。也就是說元組中不可變的是元素的標(biāo)識(shí),但元組的值會(huì)隨著引用的可變對(duì)象變化而變化。在中每個(gè)對(duì)象的引用都會(huì)有統(tǒng)計(jì)。弱引用不會(huì)妨礙對(duì)象被當(dāng)做垃圾回收。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之面向?qū)ο笃闹攸c(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、明確變量保存的是引用這一本質(zhì);2、熟悉對(duì)象引用的基礎(chǔ)知識(shí);...

    ytwman 評(píng)論0 收藏0
  • 流暢的python讀書筆記-第八章-對(duì)象引用、可變性和垃圾回收

    摘要:運(yùn)算符比較兩個(gè)對(duì)象的標(biāo)識(shí)函數(shù)返回對(duì)象標(biāo)識(shí)的整數(shù)表示。實(shí)際上,每個(gè)對(duì)象都會(huì)統(tǒng)計(jì)有多少引用指向自己。對(duì)象被銷毀了,調(diào)用了回調(diào),的值變成了。當(dāng)對(duì)象的引用數(shù)量歸零后,垃圾回收程序會(huì)把對(duì)象銷毀。引用的目標(biāo)對(duì)象稱為所指對(duì)象。 對(duì)象不是個(gè)盒子 showImg(https://segmentfault.com/img/bV95mW?w=1784&h=988); class Gizmo: def...

    zgbgx 評(píng)論0 收藏0
  • 編寫符合Python風(fēng)格的對(duì)象

    摘要:自定義向量類型從自定義向量類型入手寫出符合風(fēng)格的對(duì)象,這離不開特殊方法的支持。將對(duì)象定為不可變的通過使用兩個(gè)前導(dǎo)下劃線。程序員約定使用一個(gè)下劃線前綴編寫受保護(hù)的屬性即,他們認(rèn)為應(yīng)該使用命名約定來避免意外覆蓋屬性。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之面向?qū)ο笃闹攸c(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、掌握編寫Pythonic c...

    ethernet 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<