有关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])来完成操做,可是咱们仍然不建议这样作,不要将可变对象放入元组中。
相关文章
相关标签/搜索