python對不可變序列進行重複拼接操作效率會很低,因為每次都會生成乙個新的物件,直譯器需要把原來物件中的元素先複製到新的物件裡,然後再追加新的元素。
但是cpython對字串操作進行了優化,因為對字串做+=操作實在是太普遍了。因此,初始化str時會預留出額外的可擴充套件空間,從而進行增量操作的時候不會有複製再追加的這個步驟。
通過位元組碼研究一下這個過程。
>>> 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)
得到的位元組碼是bytes型別的。這裡穿插一些bytes型別的知識。
b'e\x00\x00d\x00\x007z\x00\x00d\x01\x00s',b表示是bytes型別。bytes以二進位制位元組序列的形式記錄資料,每乙個字元就代表乙個位元組(8位)。比如上面的e表示二進位制0110 0101。部分ascii碼對照表如下圖所示。
但是,不是所有的位元組都是可顯示的,甚至有些位元組無法對應到ascii碼上(因為ascii碼只定義了128個字元,而乙個位元組有256個)。比如0000 0000對應的ascii是不可顯示的、0111 1111沒有對應的ascii碼。
為了表示這些無法顯示的位元組,就引入了\x符號,其表示後續的字元為16進製制。如,\x00表示16進製制的00,也就是htfquoc二進位制的0000 0000。
至此,所有位元組都可被表示。
回到開始的**。為了顯示方便,將b'e\x00\x00d\x00\x007程式設計客棧z\x00\x00d\x01\x00s'轉為16進製制來顯示。
>>> c.co_code.hex()
'650000640000375a000064010053'
通過opcode.opname函式可以得到操作碼所對應的操作指令
>>> import opcode
>>> opcode.opname[0x65]
'load_name'
因此,完整的位元組碼可以解釋為(tos即top-of-stack,棧頂元素):
位元組:位置,功能
65:0,load_name
0000:引數,將co_names[0]的值,即a的值,壓入棧
64:3,load_const
0000:引數,將co_consts[0],即'b',壓入棧
37:6,inplace_add,tos = tos1 + tos
5a:7,store_name
0000:引數,co_names[0]=tos,即將棧頂賦值給a
64:10,load_const
0100:引數
53:13,return_value,returns with tos to the caller of the function
實際上借助dis函式可以直接獲得可讀的位元組碼:
>>> import dis
>>> dis.dis(s_code)
1 0 load_name 0 (a)
3 load_const 0 ('b')
6www.cppcns.com inplace
7 store_name 0 (a)
10 load_const 1 (none)
13 rhtfquoceturn_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)
非常失敗,對比了string和tuple的賦值位元組碼,並沒有看出string的優化…
python位元組碼 Python位元組碼簡介
python位元組碼 如果您曾經編寫過python,或者甚至只是使用過python,那麼您可能已經習慣了檢視python源 檔案。它們的名稱以.py結尾。而且您可能還看到了另一種型別的檔案,其名稱以.pyc結尾,並且您可能已經聽說它們是python的 位元組碼 檔案。這些在python 3上很難看到...
python 位元組碼
python位元組碼 hello.py usr bin env python coding utf 8 import m 呼叫m裡的方法 執行之後會生成乙個m.pyc檔案 如果將m.py檔案刪除,只留hello.py和m.pyc檔案,同樣能執行出效果 對於hello.py m.py m.pyc 三個...
python 位元組碼 優化 位元組碼優化
python是一種動態語言。這意味著您在編寫 方面有很大的自由度。由於python公開了大量的自省 順便說一句,這非常有用 許多優化根本無法執行。例如,在第乙個示例中,python無法知道呼叫它時list是什麼資料型別。我可以建立乙個非常奇怪的類 class crazylist object pri...