新聞中心
本文轉(zhuǎn)載自公眾號(hào)“讀芯術(shù)”(ID:AI_Discovery)

創(chuàng)新互聯(lián)主要從事成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)長(zhǎng)垣,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):028-86922220
本文將會(huì)為你介紹Python引用計(jì)數(shù),演示中使用可變列表對(duì)象,不過(guò)本文不介紹C語(yǔ)言實(shí)現(xiàn)細(xì)節(jié)。
[[328257]]
需要注意的是,代碼段的輸出在硬件上可能有所不同。
變量是內(nèi)存引用
Python中的變量是內(nèi)存引用。如果輸入x = [1,2]時(shí)會(huì)發(fā)生什么?[1,2]是對(duì)象。
回想一下,一切都是Python中的對(duì)象。[1,2]將在內(nèi)存中創(chuàng)建。x是[1,2]對(duì)象的內(nèi)存引用。
來(lái)看看下面的例子。可以找到x所引用的內(nèi)存地址。請(qǐng)務(wù)必只使用id(x),它會(huì)以10為基數(shù),而十六進(jìn)制函數(shù)會(huì)將其轉(zhuǎn)換為十六進(jìn)制。
- x = [1, 2]
- print(hex(id(x))) # output: 0x32ebea8
引用計(jì)數(shù)
現(xiàn)在已經(jīng)在內(nèi)存中創(chuàng)建了一個(gè)list對(duì)象,而且x對(duì)該對(duì)象進(jìn)行了引用。那么y=[1,2]和y=x有什么區(qū)別?
當(dāng)輸入y=[1,2]時(shí),它將在內(nèi)存中創(chuàng)建一個(gè)新的list對(duì)象,并且y將引用它。
- x = [1, 2]
- y = [1, 2]
- print(hex(id(x))) # output: 0x101bea8
- print(hex(id(y))) # output: 0x31a5528
而當(dāng)輸入y=x時(shí),等同于告訴Python希望y 變量引用x變量引用的內(nèi)容。因?yàn)樽兞渴莾?nèi)存引用的。
可以確認(rèn)x和y引用同一個(gè)對(duì)象。
- x = [1, 2]
- y = x
- print(hex(id(x))) # output: 0x74bea8
- print(hex(id(y))) # output: 0x74bea8
引用計(jì)數(shù)的數(shù)目
接下來(lái)的問(wèn)題是,有多少變量引用同一個(gè)對(duì)象?
錯(cuò)誤的用法:
我看到有些人在使用sys.getrefcount(var)時(shí)不知道如何傳遞var,而是向?qū)ο筇砑右?。一起看看下面的例子?/p>
輸出3,而期望的卻是2(x andy)。發(fā)生這種情況是因?yàn)閷傳遞給getrefcount函數(shù)時(shí)又添加了一個(gè)引用。
- from sys import getrefcount
- x = [1, 2]
- y = x
- print(hex(id(x))) # output: 0xb65748
- print(hex(id(y))) # output: 0xb65748
- print(getrefcount(x)) # output: 3
更好的用法:
可以使用內(nèi)置的ctypes模塊來(lái)找到預(yù)期的結(jié)果。必須將x的id傳遞給from_address函數(shù)。
- from ctypes import c_long
- x = [1, 2]
- y = x
- print(hex(id(x))) # output: 0x3395748
- print(hex(id(y))) # output: 0x3395748
- print(c_long.from_address(id(x)).value) # output: 2
概言之,錯(cuò)誤的用法是傳遞變量,而更好的用法則是傳遞變量的id,這意味著只傳遞基數(shù)為10的數(shù)字,而不是變量。
當(dāng)對(duì)象消失時(shí)
當(dāng)沒(méi)有變量引用對(duì)象時(shí)會(huì)發(fā)生什么?
對(duì)象將從內(nèi)存中刪除,因?yàn)闆](méi)有引用該對(duì)象的內(nèi)容。不過(guò)也有例外:如果有循環(huán)引用,garbage collector 將開(kāi)始奏效。
為什么使用可變對(duì)象
不可變對(duì)象由于性能原因,結(jié)果可能與預(yù)期不同。查看下面的例子,觀察輸出是如何變化的。
- import sys
- import ctypes
- """Some Mutable Objects """
- a =list()
- b =set()
- c =dict()
- d =bytearray()
- """ Some ImmutableObjects """
- e =tuple()
- f =int()
- g =str()
- print(sys.getrefcount(a),ctypes.c_long.from_address(id(a)).value) # output: 2 1
- print(sys.getrefcount(b),ctypes.c_long.from_address(id(b)).value) # output: 2 1
- print(sys.getrefcount(c),ctypes.c_long.from_address(id(c)).value) # output: 2 1
- print(sys.getrefcount(d),ctypes.c_long.from_address(id(d)).value) # output: 2 1
- print(sys.getrefcount(e),ctypes.c_long.from_address(id(e)).value) # output: 1298 1297
- print(sys.getrefcount(f),ctypes.c_long.from_address(id(f)).value) # output: 209 208
- print(sys.getrefcount(g),ctypes.c_long.from_address(id(g)).value) # output: 59 58
文中所談及的一切都對(duì)CPython有效。希望對(duì)你有幫助。
網(wǎng)站題目:內(nèi)存中的Python:Python引用計(jì)數(shù)指南
文章網(wǎng)址:http://fisionsoft.com.cn/article/dhsscig.html


咨詢
建站咨詢
