av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

Python小整數(shù)對(duì)象池和字符串intern實(shí)例解析

瀏覽:58日期:2022-08-01 16:27:58

is用于判斷兩個(gè)對(duì)象是否為同一個(gè)對(duì)象,具體來說是兩個(gè)對(duì)象在內(nèi)存中的位置是否相同。

python為了提高效率,節(jié)省內(nèi)存,在實(shí)現(xiàn)上大量使用了緩沖池技術(shù)和字符串intern技術(shù)。

整數(shù)和字符串是不可變對(duì)象,也就意味著可以用來共享,如100個(gè)“python”字串變量可以共享一個(gè)“python”字符串對(duì)象,而不是創(chuàng)建100個(gè)“python”字符串。

小整數(shù)對(duì)象池

為了應(yīng)對(duì)小整數(shù)的頻繁使用,python使用對(duì)小整數(shù)進(jìn)行了緩存,默認(rèn)范圍為[-5,256],在這個(gè)范圍內(nèi)的所有整數(shù)被python完全地緩存,當(dāng)有變量使用這些小整數(shù)時(shí),增加對(duì)應(yīng)小整數(shù)對(duì)象的引用即可。

>>> i = -5>>> j = -5>>> i is j # i和j是同一個(gè)對(duì)象True>>> i = 256>>> j = 256>>> i is j # i和j是同一個(gè)對(duì)象True>>> i = 257>>> j = 257>>> i is j # i和j是不同對(duì)象False

由上面的實(shí)例可以看到,當(dāng)變量在[-5,256]之間時(shí),兩個(gè)值相同的變量事實(shí)上會(huì)引用到同一個(gè)小整數(shù)對(duì)象上,也就是小整數(shù)對(duì)象池中的對(duì)象,而不會(huì)去創(chuàng)建兩個(gè)對(duì)象。而當(dāng)變量超出了這個(gè)范圍,兩個(gè)值相同的變量也會(huì)各自創(chuàng)建整數(shù)對(duì)象,所以兩者對(duì)應(yīng)的對(duì)象不同。

字符串intern

如果當(dāng)前變量引用的字符串對(duì)象已經(jīng)存在的話,直接增加對(duì)應(yīng)字符串對(duì)象的引用,而不去創(chuàng)建新的字符串對(duì)象,這就是字符串intern機(jī)制。

>>> i = '12' >>> j = '12' >>> i is j True

在詳細(xì)探討字符串intern機(jī)制之前,先看一個(gè)奇怪的問題:

>>> i = '1 2' >>> j = '1 2' >>> i is j False

i = '1 2' j = '1 2' print(i is j)

輸出結(jié)果

True

上述代碼分開運(yùn)行,結(jié)果為False,但是合在一起結(jié)果卻為True,也就是說分開運(yùn)行的時(shí)候,i,j指向不同對(duì)象,而合在一起的時(shí)候i,j卻指向了相同對(duì)象。為了明白其中的緣由,需要簡(jiǎn)單理解python的編譯機(jī)制。

編譯機(jī)制

在python中,萬物皆對(duì)象,包括代碼本身也是一種對(duì)象。python用code對(duì)象表示代碼,代碼編譯后產(chǎn)生code對(duì)象。通常一個(gè)作用域?qū)?yīng)一個(gè)code對(duì)象。

i = '1 2'j = '1 2'print(i is j)def f(): pass

編譯結(jié)果

2 0 LOAD_CONST 0 (’1 2’)2 STORE_NAME 0 (i)

3 4 LOAD_CONST 0 (’1 2’)6 STORE_NAME 1 (j)

5 8 LOAD_CONST 1 (<code object f at 0x00000200F257CF60, file 'small_int.py', line 5>)10 LOAD_CONST 2 (’f’)12 MAKE_FUNCTION 014 STORE_NAME 2 (f)16 LOAD_CONST 3 (None)18 RETURN_VALUE

Disassembly of <code object f at 0x00000200F257CF60, file 'small_int.py', line 5>:6 0 LOAD_CONST 0 (None)2 RETURN_VALUE

上述代碼中編譯生成了兩個(gè)code對(duì)象,一個(gè)代表全局作用域,另一個(gè)代表函數(shù)f。

code對(duì)象保存了變量,常量(常量字面量)以及編譯結(jié)果。code對(duì)象用常量表來保存常量,考慮到一個(gè)常量可能出現(xiàn)多次,在一張表上保存一個(gè)常量多次太過于奢侈。所以code對(duì)象對(duì)每個(gè)常量只保存一次,在需要引用它的地方使用它在常量表的位置作為常量的表示。在上述編譯結(jié)果中可以看到,'1 2'這個(gè)字符串常量使用了兩次,編譯的代碼為'LOAD_CONST 0',這里的0就是'1 2'在常量表當(dāng)中的位置。

由于編譯的這個(gè)特性,在同一個(gè)code對(duì)象中的變量,如果它們引用了同一個(gè)常量,那么無論這個(gè)常量有沒有緩沖機(jī)制,它們引用的都是同一個(gè)對(duì)象。

a = '12'b = '12'c = '1 2'd = '1 2'e = 257f = 257g = 2424234234234234h = 2424234234234234print(a is b, c is d, e is f, g is h)

輸出結(jié)果

True True True True

這個(gè)例子說明,在同一個(gè)code對(duì)象當(dāng)中,常量(字面量)僅一份,這與緩沖機(jī)制無關(guān),是編譯特性。所以對(duì)于上述那個(gè)奇怪的問題就可以解釋了,當(dāng)i,j在同一個(gè)code對(duì)象(同一個(gè)作用域)中引用常量'1 2',它們引用的都是同一個(gè)對(duì)象。而當(dāng)在python命令行中分開執(zhí)行時(shí),對(duì)于每一條語句,都是一個(gè)單獨(dú)的code對(duì)象,這時(shí)起作用的是字符串intern機(jī)制,上述運(yùn)行結(jié)果說明,字符串intern機(jī)制對(duì)'12'進(jìn)行了intern,而對(duì)'1 2'沒有進(jìn)行intern。

編譯機(jī)制與小整數(shù)對(duì)象池對(duì)比

i = 257j = 257a = i - 1b = i - 1c = i + 1d = i + 1print(i is j, a is b, c is d)

輸出結(jié)果

True True False

i和j引用同一個(gè)常量,這是編譯機(jī)制,所以i與j指向同一個(gè)整數(shù)對(duì)象,后面a和b雖然相等,但不引用常量,此時(shí)啟用小整數(shù)對(duì)象池,a,b都等于256,在對(duì)象池中,所以a,b引用同一個(gè)對(duì)象,后面c,d不在對(duì)象池中,所以兩者對(duì)象不同。

這里有一點(diǎn)需要注意,沒有變量參與的運(yùn)算會(huì)被編譯器直接優(yōu)化成對(duì)應(yīng)的常量,進(jìn)而保存進(jìn)常量表中。

字符串intern機(jī)制與字符緩沖池在編譯過程中,字符串intern機(jī)制將所有的變量名進(jìn)行intern,但對(duì)常量進(jìn)行的intern有一點(diǎn)特殊的限制。能夠intern的常量必須只包含[a-zA-Z0-9_],即字母數(shù)字加下劃線,如果含有其他字符,就不會(huì)intern。在運(yùn)行過程中,通過計(jì)算得到的字符串不會(huì)intern。

字符串有一個(gè)和小整數(shù)對(duì)象池相似的字符緩沖池,用于在運(yùn)行過程中緩存單個(gè)字符,所以計(jì)算得到的字符串雖然不會(huì)intern,但如果是單個(gè)字符,就會(huì)使用到字符緩沖池。

k = 'bbb'a = k[0]b = k[0]c = k[1:]d = k[1:]print(a, d)print(a is b, c is d)

輸出結(jié)果

b bb True False

可以看到,a和b確實(shí)指向同一個(gè)對(duì)象,而c和d指向不同對(duì)象,這就是字符緩沖池。

編譯機(jī)制與字符串intern對(duì)比

i = '1 2'j = '12'k = '__fjdslfjaskfas'ii = '1 2'jj = '12'kk = '__fjdslfjaskfas'def f(): a = '1 2' b = '12' c = '__fjdslfjaskfas' return a is i, b is j, c is kprint('Code:', i is ii, j is jj, k is kk)print(f'intern: {f()}')

輸出結(jié)果

Code: True True True intern: (False, True, True)

i包含空格,包含空格的常量不會(huì)被intern,而其他兩個(gè)常量不包含其他字符,所以會(huì)被intern。

總結(jié)

1. python代碼被編譯成code對(duì)象,通常一個(gè)code對(duì)象對(duì)應(yīng)于一個(gè)作用域,作用域中重復(fù)出現(xiàn)的變量名以及常量在code中只保存一次。

2. 字符串intern機(jī)制主要作用于編譯過程,在編譯收集完變量和常量時(shí),對(duì)變量和常量進(jìn)行intern,而后構(gòu)建一個(gè)code對(duì)象。

3. 字符串intern對(duì)常量的intern有限制,能夠intern的常量必須只包含[a-zA-Z0-9_],即字母數(shù)字加下劃線,如果含有其他字符,就不會(huì)intern。

4. 小整數(shù)對(duì)象池和字符緩沖池都是作用于運(yùn)行過程中,python緩存小的整數(shù)和字符,當(dāng)有變量使用這些對(duì)象時(shí),不用額外創(chuàng)建對(duì)象。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 久久久久亚洲精品 | 精品久久影院 | 日本一区二区高清不卡 | 午夜丰满寂寞少妇精品 | 久久精品亚洲精品国产欧美 | 操久久| 国产精品亚洲第一 | 麻豆久久 | 欧美精品福利视频 | 91精品久久久久久久久久入口 | 天堂网中文字幕在线观看 | 亚洲不卡| 免费一区| 国产精品无码专区在线观看 | 国产精品久久久久久久久久 | 中文字幕成人在线 | 日韩波多野结衣 | 亚洲精品一区二区 | 在线视频一区二区三区 | 国产高清视频一区二区 | 久久久2o19精品 | 天堂一区在线观看 | www.蜜桃av | 国产精品久久久爽爽爽麻豆色哟哟 | 亚洲精品视频在线 | 日韩av一二三区 | 91色视频在线观看 | 国产网站在线免费观看 | 成人精品久久 | 国产精品久久久久久中文字 | 亚洲av毛片成人精品 | 亚洲草草视频 | 亚洲精品永久免费 | 国产一区二区在线播放 | 久久网亚洲 | 污片在线观看 | 九九精品久久久 | 欧美视频中文字幕 | 日韩一级黄色片 | 欧产日产国产精品v | 国产精品成人久久久久 |