溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python中怎么引用計(jì)數(shù)

發(fā)布時(shí)間:2021-07-05 18:04:54 來源:億速云 閱讀:162 作者:Leah 欄目:編程語言

Python中怎么引用計(jì)數(shù),針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

回顧內(nèi)存地址

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

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

>>> a = 1 >>> b = 1 >>> id(a) 140709385600544 >>> id(b) 140709385600544

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

>>> a = [1,2] >>> b = [1,2] >>> id(a) 1966828025736 >>> id(b) 1966828044488 >>> c = a >>> id(c) 1966828025736

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

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

在一些代碼中,如果存在一些變量但是沒有用,會(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ù)來管理內(nèi)存,所有 Python 腳本中創(chuàng)建的實(shí)例,都會(huì)有一個(gè)引用計(jì)數(shù),來記錄有多少個(gè)指針指向它。當(dāng)引用計(jì)數(shù)只有 0  時(shí),則會(huì)自動(dòng)釋放內(nèi)存。

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

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è)空列表。

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

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

import sys a = [] # 兩次引用,一次來自 a,一次來自 getrefcount print(sys.getrefcount(a)) def func(a):     # 四次引用,a,python 的函數(shù)調(diào)用棧,函數(shù)參數(shù),和 getrefcount     print(sys.getrefcount(a))  func(a) # 兩次引用,一次來自 a,一次來自 getrefcount,函數(shù) func 調(diào)用已經(jīng)不存在 print(sys.getrefcount(a))  ########## 輸出 ########## 2 4 2

引用計(jì)數(shù)是用來記錄對(duì)象被引用的次數(shù),每當(dāng)對(duì)象被創(chuàng)建或者被引用時(shí)將該對(duì)象的引用次數(shù)加一,當(dāng)對(duì)象的引用被銷毀時(shí)該對(duì)象的引用次數(shù)減一,當(dāng)對(duì)象的引用次數(shù)減到零時(shí)說明程序中已經(jīng)沒有任何對(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è)變量離開了作用域,比如:函數(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)景)。

import sys  def ref_method(str):     print(sys.getrefcount(str))     print("我調(diào)用了{(lán)}".format(str))     print('方法執(zhí)行完了')  def ref_count():     # 引用計(jì)數(shù)增加的場(chǎng)景     print('測(cè)試引用計(jì)數(shù)增加')     a = 'A'     print(sys.getrefcount(a))       b = a     print(sys.getrefcount(a))     ref_method(a)     print(sys.getrefcount(a))     c = [1, a, 'abc']     print(sys.getrefcount(a))      # 引用計(jì)數(shù)減少的場(chǎng)景     print('測(cè)試引用計(jì)數(shù)減少')     del b     print(sys.getrefcount(a))     c.remove(a)     print(sys.getrefcount(a))     del c     print(sys.getrefcount(a))     a = 783     print(sys.getrefcount(a))  if __name__ == '__main__':     ref_count()   ########## 輸出 ########## 測(cè)試引用計(jì)數(shù)增加 78   #77+1 77在函數(shù)中是隨機(jī)的 79 81 我調(diào)用了A 方法執(zhí)行完了 79 80 測(cè)試引用計(jì)數(shù)減少 79 78 78 4

關(guān)于Python中怎么引用計(jì)數(shù)問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI