偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

深入Python中引用計(jì)數(shù)

開(kāi)發(fā) 后端
在python中的垃圾回收機(jī)制主要是以引用計(jì)數(shù)為主要手段以標(biāo)記清除和隔代回收機(jī)制為輔的手段 ??梢詫?duì)內(nèi)存中無(wú)效數(shù)據(jù)的自動(dòng)管理!在這篇文章,帶著這個(gè)問(wèn)題來(lái)一直往下看:怎么知道一個(gè)對(duì)象能不能被調(diào)用了呢?

[[351330]]

 在python中的垃圾回收機(jī)制主要是以引用計(jì)數(shù)為主要手段以標(biāo)記清除和隔代回收機(jī)制為輔的手段 ??梢詫?duì)內(nèi)存中無(wú)效數(shù)據(jù)的自動(dòng)管理!在這篇文章,帶著這個(gè)問(wèn)題來(lái)一直往下看:怎么知道一個(gè)對(duì)象能不能被調(diào)用了呢?

回顧內(nèi)存地址

Python中的任何變量都有對(duì)應(yīng)的內(nèi)存引用,也就是內(nèi)存地址。

如果不是容器類型,那么直接引用和賦值,內(nèi)存地址都是不會(huì)的。

  1. >>> a = 1 
  2. >>> b = 1 
  3. >>> id(a) 
  4. 140709385600544 
  5. >>> id(b) 
  6. 140709385600544 

如果在內(nèi)存中創(chuàng)建了一個(gè)list對(duì)象(容器),而且對(duì)該對(duì)象進(jìn)行了引用。那么b = [1,2]和c = a有什么區(qū)別?

  1. >>> a = [1,2] 
  2. >>> b = [1,2] 
  3. >>> id(a) 
  4. 1966828025736 
  5. >>> id(b) 
  6. 1966828044488 
  7. >>> c = a 
  8. >>> id(c) 
  9. 1966828025736 

首先在內(nèi)存1966828025736處創(chuàng)建了一個(gè)列表 [1,2],然后定義了一個(gè)名為a的變量。b = [1,2]會(huì)新開(kāi)一個(gè)內(nèi)存地址,c = a直接賦值直接引用[1,2]的內(nèi)存地址。

引用計(jì)數(shù)

在一些代碼中,如果存在一些變量但是沒(méi)有用,會(huì)造成內(nèi)存空間,因此叫做垃圾,所以要回收。

引用計(jì)數(shù)也是一種最直觀,最簡(jiǎn)單的垃圾收集技術(shù)。原理非常簡(jiǎn)單,每一個(gè)對(duì)象都包含了兩個(gè)頭部信息,一個(gè)是類型標(biāo)志符,標(biāo)識(shí)這個(gè)對(duì)象的類型;另一個(gè)是計(jì)數(shù)器,記錄當(dāng)前指向該對(duì)象的引用數(shù)目,表示這個(gè)對(duì)象被多少個(gè)變量名所引用。

CPython 使用引用計(jì)數(shù)來(lái)管理內(nèi)存,所有 Python 腳本中創(chuàng)建的實(shí)例,都會(huì)有一個(gè)引用計(jì)數(shù),來(lái)記錄有多少個(gè)指針指向它。當(dāng)引用計(jì)數(shù)只有 0 時(shí),則會(huì)自動(dòng)釋放內(nèi)存。

在Python中通過(guò)sys.getrefcount查看引用計(jì)數(shù)的方法,

  1. print(sys.getrefcount()) 

注意調(diào)用getrefcount()函數(shù)會(huì)臨時(shí)增加一次引用計(jì)數(shù),得到的結(jié)果比預(yù)期的多一次。

比如,下面這個(gè)例子中,a 的引用計(jì)數(shù)是 3,因?yàn)橛?a、b 和作為參數(shù)傳遞的 getrefcount 這三個(gè)地方,都引用了一個(gè)空列表。

  1. >>> import sys 
  2. >>> a = [] 
  3. >>> b = a 
  4. >>> print(sys.getrefcount(a)) 

我們通過(guò)一些例子來(lái)看下,可以使python對(duì)象的引用計(jì)數(shù)增加或減少的場(chǎng)景。

  1. import sys 
  2. a = [] 
  3. # 兩次引用,一次來(lái)自 a,一次來(lái)自 getrefcount 
  4. print(sys.getrefcount(a)) 
  5. def func(a): 
  6.     # 四次引用,a,python 的函數(shù)調(diào)用棧,函數(shù)參數(shù),和 getrefcount 
  7.     print(sys.getrefcount(a)) 
  8.  
  9. func(a) 
  10. # 兩次引用,一次來(lái)自 a,一次來(lái)自 getrefcount,函數(shù) func 調(diào)用已經(jīng)不存在 
  11. print(sys.getrefcount(a)) 
  12.  
  13. ########## 輸出 ########## 

引用計(jì)數(shù)是用來(lái)記錄對(duì)象被引用的次數(shù),每當(dāng)對(duì)象被創(chuàng)建或者被引用時(shí)將該對(duì)象的引用次數(shù)加一,當(dāng)對(duì)象的引用被銷毀時(shí)該對(duì)象的引用次數(shù)減一,當(dāng)對(duì)象的引用次數(shù)減到零時(shí)說(shuō)明程序中已經(jīng)沒(méi)有任何對(duì)象持有該對(duì)象的引用,換言之就是在以后的程序運(yùn)行中不會(huì)再次使用到該對(duì)象了,那么其所占用的空間也就可以被釋放了了。

計(jì)數(shù)增加和減少

下面引用計(jì)數(shù)增加的場(chǎng)景:

  • 對(duì)象被創(chuàng)建并賦值給某個(gè)變量,比如:a = 'ABC'
  • 變量間的相互引用(相當(dāng)于變量指向了同一個(gè)對(duì)象),比如:b=a
  • 變量作為參數(shù)傳到函數(shù)中。比如:ref_method(a),
  • 將對(duì)象放到某個(gè)容器對(duì)象中(列表、元組、字典)。比如:c = [1, a, 'abc']

引用計(jì)數(shù)減少的場(chǎng)景:

  • 當(dāng)一個(gè)變量離開(kāi)了作用域,比如:函數(shù)執(zhí)行完成時(shí),執(zhí)行方法前后的引用計(jì)數(shù)保持不變,這就是因?yàn)榉椒▓?zhí)行完后,對(duì)象的引用計(jì)數(shù)也會(huì)減少,如果在方法內(nèi)打印,則能看到引用計(jì)數(shù)增加的效果。
  • 對(duì)象的引用變量被銷毀時(shí),比如del a或者del b。注意如果del a,再去獲取a的引用計(jì)數(shù)會(huì)直接報(bào)錯(cuò)。
  • 對(duì)象被從容器對(duì)象中移除,比如:c.remove(a)
  • 直接將整個(gè)容器銷毀,比如:del c
  • 對(duì)象的引用被賦值給其他對(duì)象,相當(dāng)于變量不指向之前的對(duì)象,而是指向了一個(gè)新的對(duì)象,這種情況,引用計(jì)數(shù)肯定會(huì)發(fā)生改變。(排除兩個(gè)對(duì)象默認(rèn)引用計(jì)一致的場(chǎng)景)。
  1. import sys 
  2.  
  3. def ref_method(str): 
  4.     print(sys.getrefcount(str)) 
  5.     print("我調(diào)用了{(lán)}".format(str)) 
  6.     print('方法執(zhí)行完了'
  7.  
  8. def ref_count(): 
  9.     # 引用計(jì)數(shù)增加的場(chǎng)景 
  10.     print('測(cè)試引用計(jì)數(shù)增加'
  11.     a = 'A' 
  12.     print(sys.getrefcount(a))   
  13.     b = a 
  14.     print(sys.getrefcount(a)) 
  15.     ref_method(a) 
  16.     print(sys.getrefcount(a)) 
  17.     c = [1, a, 'abc'
  18.     print(sys.getrefcount(a)) 
  19.  
  20.     # 引用計(jì)數(shù)減少的場(chǎng)景 
  21.     print('測(cè)試引用計(jì)數(shù)減少'
  22.     del b 
  23.     print(sys.getrefcount(a)) 
  24.     c.remove(a) 
  25.     print(sys.getrefcount(a)) 
  26.     del c 
  27.     print(sys.getrefcount(a)) 
  28.     a = 783 
  29.     print(sys.getrefcount(a)) 
  30.  
  31. if __name__ == '__main__'
  32.     ref_count() 
  33.  
  34.  
  35. ########## 輸出 ########## 
  36. 測(cè)試引用計(jì)數(shù)增加 
  37. 78   #77+1 77在函數(shù)中是隨機(jī)的 
  38. 79 
  39. 81 
  40. 我調(diào)用了A 
  41. 方法執(zhí)行完了 
  42. 79 
  43. 80 
  44. 測(cè)試引用計(jì)數(shù)減少 
  45. 79 
  46. 78 
  47. 78 

本文已收錄 GitHub,傳送門~[2] ,里面更有大廠面試完整考點(diǎn),歡迎 Star。

 

責(zé)任編輯:姜華 來(lái)源: Python之王
相關(guān)推薦

2020-05-31 18:08:15

Python數(shù)據(jù)技術(shù)

2023-03-26 22:48:46

Python引用計(jì)數(shù)內(nèi)存

2017-10-12 12:41:11

PHP圾回收機(jī)制變量容器

2015-02-01 10:38:47

Linus并行計(jì)算

2010-03-29 09:11:02

Python引用計(jì)數(shù)

2010-08-19 09:24:41

iPhone

2013-08-21 10:53:46

iOS定義區(qū)別

2021-10-18 15:50:49

Android強(qiáng)引用軟引用

2024-05-13 08:35:27

PyObjectPython對(duì)象

2021-08-10 07:27:42

Python引用計(jì)數(shù)法

2020-02-09 17:23:17

Python數(shù)據(jù)字典

2009-09-11 11:09:36

C#引用類型

2021-05-27 21:47:12

Python垃圾回收

2020-11-11 08:24:06

collection

2020-11-06 13:42:59

itertools

2020-11-05 08:56:19

Python

2021-12-09 15:45:09

Python弱引用代碼

2010-03-15 12:36:26

Python列表

2023-11-27 15:08:52

Python編程語(yǔ)言

2020-11-12 08:52:16

Python
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)