最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python語(yǔ)法?之垃圾回收機(jī)制

 更新時(shí)間:2022年04月13日 15:36:34   作者:JasonJi  
這篇文章主要介紹了python語(yǔ)法?之垃圾回收機(jī)制,垃圾回收機(jī)制?是Python解釋器自帶一種機(jī),專門用來回收不可用的變量值所占用的內(nèi)存空間,下文相關(guān)介紹,需要的朋友可以參考一下

一 引入

? 解釋器在執(zhí)行到定義變量的語(yǔ)法時(shí),會(huì)申請(qǐng)內(nèi)存空間來存放變量的值,而內(nèi)存的容量是有限的,這就涉及到變量值所占用內(nèi)存空間的回收問題,當(dāng)一個(gè)變量值沒有用了(簡(jiǎn)稱垃圾)就應(yīng)該將其占用的內(nèi)存給回收掉,那什么樣的變量值是沒有用的呢?

? 由于變量名是訪問到變量值的唯一方式,所以當(dāng)一個(gè)變量值不再關(guān)聯(lián)任何變量名時(shí),我們就無法再訪問到該變量值了,該變量值就是沒有用的,就應(yīng)該被當(dāng)成一個(gè)垃圾回收。毫無疑問,內(nèi)存空間的申請(qǐng)與回收是非常耗費(fèi)精力的事情,而且存在很大的危險(xiǎn)性,稍有不慎就有可能引發(fā)內(nèi)存溢出問題,好在Cpython解釋器提供了自動(dòng)的垃圾回收機(jī)制來幫我們解決了這件事。

二、什么是垃圾回收機(jī)制?

垃圾回收機(jī)制(簡(jiǎn)稱GC)是Python解釋器自帶一種機(jī),專門用來回收不可用的變量值所占用的內(nèi)存空間

三、為什么要用垃圾回收機(jī)制?

程序運(yùn)行過程中會(huì)申請(qǐng)大量的內(nèi)存空間,而對(duì)于一些無用的內(nèi)存空間如果不及時(shí)清理的話會(huì)導(dǎo)致內(nèi)存使用殆盡(內(nèi)存溢出),導(dǎo)致程序崩潰,因此管理內(nèi)存是一件重要且繁雜的事情,而python解釋器自帶的垃圾回收機(jī)制把程序員從繁雜的內(nèi)存管理中解放出來。

四、垃圾回收機(jī)制原理分析

Python的GC模塊主要運(yùn)用了“引用計(jì)數(shù)”(reference counting)來跟蹤和回收垃圾。在引用計(jì)數(shù)的基礎(chǔ)上,還可以通過“標(biāo)記-清除”(mark and sweep)解決容器對(duì)象可能產(chǎn)生的循環(huán)引用的問題,并且通過“分代回收”(generation collection)以空間換取時(shí)間的方式來進(jìn)一步提高垃圾回收的效率。

4.1、什么是引用計(jì)數(shù)?

引用計(jì)數(shù)就是:變量值被變量名關(guān)聯(lián)的次數(shù)

如:age=18

變量值18被關(guān)聯(lián)了一個(gè)變量名age,稱之為引用計(jì)數(shù)為1

引用計(jì)數(shù)增加:

age=18 (此時(shí),變量值18的引用計(jì)數(shù)為1)

m=age (把a(bǔ)ge的內(nèi)存地址給了m,此時(shí),m,age都關(guān)聯(lián)了18,所以變量值18的引用計(jì)數(shù)為2)

引用計(jì)數(shù)減少:

age=10(名字age先與值18解除關(guān)聯(lián),再與3建立了關(guān)聯(lián),變量值18的引用計(jì)數(shù)為1)

del m(del的意思是解除變量名x與變量值18的關(guān)聯(lián)關(guān)系,此時(shí),變量18的引用計(jì)數(shù)為0)

值18的引用計(jì)數(shù)一旦變?yōu)?,其占用的內(nèi)存地址就應(yīng)該被解釋器的垃圾回收機(jī)制回收

4.2、引用計(jì)數(shù)擴(kuò)展閱讀

變量值被關(guān)聯(lián)次數(shù)的增加或減少,都會(huì)引發(fā)引用計(jì)數(shù)機(jī)制的執(zhí)行(增加或減少值的引用計(jì)數(shù)),這存在明顯的效率問題。

如果說執(zhí)行效率還僅僅是引用計(jì)數(shù)機(jī)制的一個(gè)軟肋的話,那么很不幸,引用計(jì)數(shù)機(jī)制還存在著一個(gè)致命的弱點(diǎn),即循環(huán)引用(也稱交叉引用)

# 如下我們定義了兩個(gè)列表,簡(jiǎn)稱列表1與列表2,變量名l1指向列表1,變量名l2指向列表2
>>> l1=['xxx']  # 列表1被引用一次,列表1的引用計(jì)數(shù)變?yōu)?   
>>> l2=['yyy']  # 列表2被引用一次,列表2的引用計(jì)數(shù)變?yōu)?   
>>> l1.append(l2)             # 把列表2追加到l1中作為第二個(gè)元素,列表2的引用計(jì)數(shù)變?yōu)?
>>> l2.append(l1)             # 把列表1追加到l2中作為第二個(gè)元素,列表1的引用計(jì)數(shù)變?yōu)?

# l1與l2之間有相互引用
# l1 = ['xxx'的內(nèi)存地址,列表2的內(nèi)存地址]
# l2 = ['yyy'的內(nèi)存地址,列表1的內(nèi)存地址]
>>> l1
['xxx', ['yyy', [...]]]
>>> l2
['yyy', ['xxx', [...]]]
>>> l1[1][1][0]
'xxx'

循環(huán)引用會(huì)導(dǎo)致:值不再被任何名字關(guān)聯(lián),但是值的引用計(jì)數(shù)并不會(huì)為0,應(yīng)該被回收但不能被回收,什么意思呢?試想一下,請(qǐng)看如下操作

>>> del l1 # 列表1的引用計(jì)數(shù)減1,列表1的引用計(jì)數(shù)變?yōu)?
>>> del l2 # 列表2的引用計(jì)數(shù)減1,列表2的引用計(jì)數(shù)變?yōu)?

此時(shí),只剩下列表1與列表2之間的相互引用,兩個(gè)列表的引用計(jì)數(shù)均不為0,但兩個(gè)列表不再被任何其他對(duì)象關(guān)聯(lián),沒有任何人可以再引用到它們,所以它倆占用內(nèi)存空間應(yīng)該被回收,但由于相互引用的存在,每一個(gè)對(duì)象的引用計(jì)數(shù)都不為0,因此這些對(duì)象所占用的內(nèi)存永遠(yuǎn)不會(huì)被釋放,所以循環(huán)引用是致命的,這與手動(dòng)進(jìn)行內(nèi)存管理所產(chǎn)生的內(nèi)存泄露毫無區(qū)別。
所以Python引入了“標(biāo)記-清除” 與“分代回收”來分別解決引用計(jì)數(shù)的循環(huán)引用與效率低的問題

4.2.1 標(biāo)記-清除

容器對(duì)象(比如:list,set,dict,class,instance)都可以包含對(duì)其他對(duì)象的引用,所以都可能產(chǎn)生循環(huán)引用。而“標(biāo)記-清除”計(jì)數(shù)就是為了解決循環(huán)引用的問題。

在了解標(biāo)記清除算法前,我們需要明確一點(diǎn),關(guān)于變量的存儲(chǔ),內(nèi)存中有兩塊區(qū)域:堆區(qū)與棧區(qū),在定義變量時(shí),變量名與值內(nèi)存地址的關(guān)聯(lián)關(guān)系存放于棧區(qū),變量值存放于堆區(qū),內(nèi)存管理回收的則是堆區(qū)的內(nèi)容,詳解如下圖,

定義了兩個(gè)變量x = 10、y = 20

當(dāng)我們執(zhí)行x=y時(shí),內(nèi)存中的棧區(qū)與堆區(qū)變化如下

標(biāo)記/清除算法的做法是當(dāng)應(yīng)用程序可用的內(nèi)存空間被耗盡的時(shí),就會(huì)停止整個(gè)程序,然后進(jìn)行兩項(xiàng)工作,第一項(xiàng)則是標(biāo)記,第二項(xiàng)則是清除

1、標(biāo)記

標(biāo)記的過程其實(shí)就是,遍歷所有的GC Roots對(duì)象(棧區(qū)中的所有內(nèi)容或者線程都可以作為GC Roots對(duì)象),然后將所有GC Roots的對(duì)象可以直接或間接訪問到的對(duì)象標(biāo)記為存活的對(duì)象,其余的均為非存活對(duì)象,應(yīng)該被清除。

2、清除

清除的過程將遍歷堆中所有的對(duì)象,將沒有標(biāo)記的對(duì)象全部清除掉。

直接引用指的是從棧區(qū)出發(fā)直接引用到的內(nèi)存地址,間接引用指的是從棧區(qū)出發(fā)引用到堆區(qū)后再進(jìn)一步引用到的內(nèi)存地址,以我們之前的兩個(gè)列表l1與l2為例畫出如下圖像

當(dāng)我們同時(shí)刪除l1與l2時(shí),會(huì)清理到棧區(qū)中l(wèi)1與l2的內(nèi)容

這樣在啟用標(biāo)記清除算法時(shí),發(fā)現(xiàn)棧區(qū)內(nèi)不再有l(wèi)1與l2(只剩下堆區(qū)內(nèi)二者的相互引用),于是列表1與列表2都沒有被標(biāo)記為存活,二者會(huì)被清理掉,這樣就解決了循環(huán)引用帶來的內(nèi)存泄漏問題。

4.2.2 分代回收

背景:

基于引用計(jì)數(shù)的回收機(jī)制,每次回收內(nèi)存,都需要把所有對(duì)象的引用計(jì)數(shù)都遍歷一遍,這是非常消耗時(shí)間的,于是引入了分代回收來提高回收效率,分代回收采用的是用“空間換時(shí)間”的策略。

分代:

分代回收的核心思想是:在歷經(jīng)多次掃描的情況下,都沒有被回收的變量,gc機(jī)制就會(huì)認(rèn)為,該變量是常用變量,gc對(duì)其掃描的頻率會(huì)降低,具體實(shí)現(xiàn)原理如下:

分代指的是根據(jù)存活時(shí)間來為變量劃分不同等級(jí)(也就是不同的代)

新定義的變量,放到新生代這個(gè)等級(jí)中,假設(shè)每隔1分鐘掃描新生代一次,如果發(fā)現(xiàn)變量依然被引用,那么該對(duì)象的權(quán)重(權(quán)重本質(zhì)就是個(gè)整數(shù))加一,當(dāng)變量的權(quán)重大于某個(gè)設(shè)定得值(假設(shè)為3),會(huì)將它移動(dòng)到更高一級(jí)的青春代,青春代的gc掃描的頻率低于新生代(掃描時(shí)間間隔更長(zhǎng)),假設(shè)5分鐘掃描青春代一次,這樣每次gc需要掃描的變量的總個(gè)數(shù)就變少了,節(jié)省了掃描的總時(shí)間,接下來,青春代中的對(duì)象,也會(huì)以同樣的方式被移動(dòng)到老年代中。也就是等級(jí)(代)越高,被垃圾回收機(jī)制掃描的頻率越低
 

回收:

回收依然是使用引用計(jì)數(shù)作為回收的依據(jù)

雖然分代回收可以起到提升效率的效果,但也存在一定的缺點(diǎn):

例如一個(gè)變量剛剛從新生代移入青春代,該變量的綁定關(guān)系就解除了,該變量應(yīng)該被回收,但青春代的掃描頻率低于新生代,所以

到此這篇關(guān)于python語(yǔ)法 之垃圾回收機(jī)制的文章就介紹到這了,更多相關(guān)python 垃圾回收機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python 發(fā)送SMTP郵件的簡(jiǎn)單教程

    Python 發(fā)送SMTP郵件的簡(jiǎn)單教程

    SMTP(Simple Mail Transfer Protocol)簡(jiǎn)單郵件傳輸協(xié)議,Python內(nèi)置對(duì)SMTP的支持,可以發(fā)送純文本文件,HTML郵件以及附帶文件。本文講解如何使用python發(fā)送郵件
    2021-06-06
  • OpenCV圖像處理之自定義濾波

    OpenCV圖像處理之自定義濾波

    濾波處理分為兩大類:線性濾波和非線性濾波,OpenCV里有這些濾波的函數(shù),使用起來非常方便,這篇文章主要給大家介紹了關(guān)于OpenCV圖像處理之自定義濾波的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Python垃圾回收及Linux?Fork

    Python垃圾回收及Linux?Fork

    這篇文章主要介紹了Python垃圾回收及Linux?Forkm,Python垃圾回收主要以引用計(jì)數(shù)為主,分代回收為輔,而一個(gè)進(jìn)程調(diào)用fork()函數(shù)后,系統(tǒng)先給新的進(jìn)程分配資源,例如存儲(chǔ)數(shù)據(jù)和代碼的空間,下面來看文章具體介紹吧
    2022-01-01
  • Django如何實(shí)現(xiàn)密碼錯(cuò)誤報(bào)錯(cuò)提醒

    Django如何實(shí)現(xiàn)密碼錯(cuò)誤報(bào)錯(cuò)提醒

    這篇文章主要介紹了Django如何實(shí)現(xiàn)密碼錯(cuò)誤報(bào)錯(cuò)提醒,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值
    2020-09-09
  • python實(shí)現(xiàn)圖片變亮或者變暗的方法

    python實(shí)現(xiàn)圖片變亮或者變暗的方法

    這篇文章主要介紹了python實(shí)現(xiàn)圖片變亮或者變暗的方法,涉及Python中Image模塊操作圖片的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • python中id函數(shù)運(yùn)行方式

    python中id函數(shù)運(yùn)行方式

    在本篇文章里小編給大家分享了關(guān)于python中id函數(shù)運(yùn)行方式及相關(guān)實(shí)例,需要的朋友們可以參考下。
    2020-07-07
  • 如何使用Python處理登錄與驗(yàn)證碼

    如何使用Python處理登錄與驗(yàn)證碼

    Python 爬蟲在抓取需要登錄的網(wǎng)站數(shù)據(jù)時(shí),通常會(huì)遇到兩個(gè)主要問題:登錄驗(yàn)證和驗(yàn)證碼處理,這些機(jī)制是網(wǎng)站用來防止自動(dòng)化程序過度抓取數(shù)據(jù)的主要手段,本文將詳細(xì)講解如何使用 Python 處理登錄與驗(yàn)證碼,以便進(jìn)行順利的數(shù)據(jù)抓取,需要的朋友可以參考下
    2024-11-11
  • Python3里的super()和__class__使用介紹

    Python3里的super()和__class__使用介紹

    這篇文章主要介紹了Python3里的super()和__class__使用介紹,本文用實(shí)例講解了這兩個(gè)方法之間的關(guān)系,需要的朋友可以參考下
    2015-04-04
  • Python實(shí)現(xiàn)學(xué)生管理系統(tǒng)的代碼(JSON模塊)

    Python實(shí)現(xiàn)學(xué)生管理系統(tǒng)的代碼(JSON模塊)

    這篇文章主要介紹了Python實(shí)現(xiàn)學(xué)生管理系統(tǒng)的代碼(JSON模塊),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Tensorflow之Saver的用法詳解

    Tensorflow之Saver的用法詳解

    本篇文章主要介紹了Tensorflow之Saver的用法詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04

最新評(píng)論

左贡县| 沂水县| 泾川县| 诏安县| 习水县| 卓资县| 阿坝| 都江堰市| 丹巴县| 高青县| 神农架林区| 临澧县| 周口市| 新疆| 富顺县| 农安县| 娱乐| 个旧市| 苏尼特右旗| 鹤壁市| 铜鼓县| 清水县| 隆回县| 揭阳市| 文安县| 班戈县| 洪泽县| 涪陵区| 龙口市| 邢台县| 垦利县| 高平市| 顺昌县| 巴青县| 沽源县| 盘锦市| 巴里| 平塘县| 宜君县| 信阳市| 高台县|