改变一个扭曲的列表:幕后发生了什么

时间:2012-10-16 20:15:30

标签: python list

在python中,您可以更改如下列表:

In [303]: x = [1,2,3,4,5,6]

In [304]: x[x <= 3]+=3

In [305]: x
Out[306]: [4, 2, 3, 4, 5, 6]

我已经知道了一段时间了,但我不认为我完全理解幕后发生的事情。如果有人能抽出时间解释,我会很高兴。

In [307]: x = [1,2,3,4,5,6]

In [308]: dis.dis('x[x <= 3]+=3')
          0 SETUP_LOOP      30811 (to 30814)
          3 SLICE+2        
          4 STORE_SUBSCR   
          5 DELETE_SUBSCR  
          6 SLICE+2        
          7 DELETE_SLICE+1 
          8 FOR_ITER        15659 (to 15670)
         11 DELETE_SLICE+1 

In [309]: x
Out[309]: [1, 2, 3, 4, 5, 6]

In [310]: x[x <= 3]+=3

In [311]: x
Out[311]: [4, 2, 3, 4, 5, 6]

In [312]: x<=3
Out[312]: False

In [313]: x[False]+=3

In [314]: x
Out[314]: [7, 2, 3, 4, 5, 6]

1 个答案:

答案 0 :(得分:10)

x <= 3是一个布尔表达式。由于在Python中,boolean类型是int的子类,False结果被解释为0,因此最终效果为:

x[0] += 3

或者,以不同的方式展示:

>>> False == 0
True
>>> True == 1
True
>>> isinstance(False, int)
True

dis.dis()方法不适用于字符串;它适用于代码对象(或包含代码的东西,如函数,方法,类或模块)或字节码。事实上它似乎能够解码你的字符串是一个愉快的巧合; SETUP_LOOP是操作码120(x的ASCII值),整个字符串被解释为一组操作码和偏移量。

改为使用函数:

>>> def foo(): x[x <= 3]+=3
... 
>>> dis.dis(foo)
  1           0 LOAD_GLOBAL              0 (x)
              3 LOAD_GLOBAL              0 (x)
              6 LOAD_CONST               1 (3)
              9 COMPARE_OP               1 (<=)
             12 DUP_TOPX                 2
             15 BINARY_SUBSCR       
             16 LOAD_CONST               1 (3)
             19 INPLACE_ADD         
             20 ROT_THREE           
             21 STORE_SUBSCR        
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE