有關Python2.x版本下的dis模塊的使用

有關Python2.x版本下的dis模塊的使用

  事情源於昨天看書看到一個有意思的部分,就是在Python元組裏面的元素若是存在可變的對象,好比Python裏面的列表,相似下面這種形式:測試

t = (1, 2, [3, 4])

  那麼若是我執行t[2] += [5, 6]會發生什麼,首先給個人感受是這個會報錯吧,這個是顯而易見的,可是5可否添加進去呢?哈哈,忽然以爲有點意思了,而後答案就是:code

t變成(1, 2, [3, 4, 5, 6])
由於tuple不支持對它的賦值,因此會拋出TypeError異常

  具體的報錯信息能夠在交互式環境中自行測試一下
  這個時候咱們可使用Python的dis模塊來反編譯一下,看看操做的字節碼,以下所示:對象

In [14]: dis.dis(compile("t[2]+=[5, 6]", " ", "single"))
  1           0 LOAD_NAME                0 (t)
              3 LOAD_CONST               0 (2)
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR
             10 LOAD_CONST               1 (5)
             13 LOAD_CONST               2 (6)
             16 BUILD_LIST               2
             19 INPLACE_ADD
             20 ROT_THREE
             21 STORE_SUBSCR
             22 LOAD_CONST               3 (None)
             25 RETURN_VALUE

  由於我使用的是Python2的版本,因此在使用dis.dis的時候,咱們須要先將代碼編譯一下,即便用compile方法,這裏須要注意的是第三個參數,第三個參數有三個選項,"single"、"eval"、"exec",具體的能夠help查看一下,下面咱們來講一下上面字節碼的關鍵行的解釋:編譯

BINARY_SUBSCR 表示將t[2]存入棧頂TOS
INPLACE_ADD 表示計算 TOS+[5, 6],這一步是能夠完成的,由於TOS指向的是一個可變對象,也就是[3, 4]這個列表
STORE_SUBSCR 這一步失敗,這是由於t是一個元組,是不可變的,對其元素進行賦值是不被容許的

  因此個人建議是:方法

  • 不要把可變對象放入元組裏面
  • 增量賦值不是一個原子操做,像上面的那樣,雖然拋出錯誤,可是仍是完成了操做
  • 瞭解Python代碼背後的運行機制頗有幫助
  • 不建議這樣,雖然咱們可使用t[2].extend([5, 6])來完成操做,可是咱們仍然不建議這樣作,不要將可變對象放入元組中。
相關文章
相關標籤/搜索