溫馨提示×

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

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

詳解python字節(jié)碼

發(fā)布時(shí)間:2020-09-02 19:05:13 來(lái)源:腳本之家 閱讀:158 作者:Titan0427 欄目:開(kāi)發(fā)技術(shù)

Python對(duì)不可變序列進(jìn)行重復(fù)拼接操作效率會(huì)很低,因?yàn)槊看味紩?huì)生成一個(gè)新的對(duì)象,解釋器需要把原來(lái)對(duì)象中的元素先復(fù)制到新的對(duì)象里,然后再追加新的元素。

但是CPython對(duì)字符串操作進(jìn)行了優(yōu)化,因?yàn)閷?duì)字符串做+=操作實(shí)在是太普遍了。因此,初始化str時(shí)會(huì)預(yù)留出額外的可擴(kuò)展空間,從而進(jìn)行增量操作的時(shí)候不會(huì)有復(fù)制再追加的這個(gè)步驟。

通過(guò)字節(jié)碼研究一下這個(gè)過(guò)程。

>>> s_code = 'a += "b"'
>>> c = compile(s_code, '', 'exec')
>>> c.co_code
b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S'
>>> c.co_names
('a',)
>>> c.co_consts
('b', None)

得到的字節(jié)碼是Bytes類(lèi)型的。這里穿插一些Bytes類(lèi)型的知識(shí)。

Bytes類(lèi)型

b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S',b表示是Bytes類(lèi)型。Bytes以二進(jìn)制字節(jié)序列的形式記錄數(shù)據(jù),每一個(gè)字符就代表一個(gè)字節(jié)(8位)。比如上面的e表示二進(jìn)制0110 0101。部分ASCII碼對(duì)照表如下圖所示。

但是,不是所有的字節(jié)都是可顯示的,甚至有些字節(jié)無(wú)法對(duì)應(yīng)到ASCII碼上(因?yàn)锳SCII碼只定義了128個(gè)字符,而一個(gè)字節(jié)有256個(gè))。比如0000 0000對(duì)應(yīng)的ASCII是不可顯示的、0111 1111沒(méi)有對(duì)應(yīng)的ASCII碼。

為了表示這些無(wú)法顯示的字節(jié),就引入了\x符號(hào),其表示后續(xù)的字符為16進(jìn)制。如,\x00表示16進(jìn)制的00,也就是二進(jìn)制的0000 0000。

至此,所有字節(jié)都可被表示。

字節(jié)碼分析

回到開(kāi)始的代碼。為了顯示方便,將b'e\x00\x00d\x00\x007Z\x00\x00d\x01\x00S'轉(zhuǎn)為16進(jìn)制來(lái)顯示。

>>> c.co_code.hex()
'650000640000375a000064010053'

通過(guò)opcode.opname函數(shù)可以得到操作碼所對(duì)應(yīng)的操作指令

>>> import opcode
>>> opcode.opname[0x65]
'LOAD_NAME'

因此,完整的字節(jié)碼可以解釋為(TOS即top-of-stack,棧頂元素):

字節(jié):位置,功能
65:0,LOAD_NAME
0000:參數(shù),將co_names[0]的值,即a的值,壓入棧
64:3,LOAD_CONST
0000:參數(shù),將co_consts[0],即'b',壓入棧
37:6,INPLACE_ADD,TOS = TOS1 + TOS
5a:7,STORE_NAME
0000:參數(shù),co_names[0]=TOS,即將棧頂賦值給a
64:10,LOAD_CONST
0100:參數(shù)
53:13,RETURN_VALUE,Returns with TOS to the caller of the function

實(shí)際上借助dis函數(shù)可以直接獲得可讀的字節(jié)碼:

>>> import dis
>>> dis.dis(s_code)
 1      0 LOAD_NAME        0 (a)
       3 LOAD_CONST        0 ('b')
       6 INPLACE_ADD
       7 STORE_NAME        0 (a)
       10 LOAD_CONST        1 (None)
       13 RETURN_VALUE

完整代碼:

s_code = 'a += "b"'
c = compile(s_code, '', 'exec')
c.co_code
c.co_names
c.co_consts
c.co_code.hex()
import dis
dis.dis(s_code)

非常失敗,對(duì)比了string和tuple的賦值字節(jié)碼,并沒(méi)有看出string的優(yōu)化…

以上就是本次關(guān)于python字節(jié)碼的相關(guān)知識(shí)點(diǎn),感謝你對(duì)億速云的支持。

向AI問(wèn)一下細(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