Why do Python emit STORE_SUBSTR when there's already an INPLACE_ADD?

和自甴很熟 提交于 2020-01-03 03:00:32

问题


If you disassemble the following function

def test():
    t = (1, 2, [30])
    t[2] += [40]
    return t

You'll see that the corresponding bytecode for t[2] += [40] looks like this:

  3          18 LOAD_FAST                0 (t)
             21 LOAD_CONST               2 (2)
             24 DUP_TOPX                 2
             27 BINARY_SUBSCR
             28 LOAD_CONST               4 (40)
             31 BUILD_LIST               1
             34 INPLACE_ADD
             35 ROT_THREE
             36 STORE_SUBSCR

[40] is concatenated to the list stored in t[2] after INPLACE_ADD, why does Python decide to add a STORE_SUBSCR anyway?


回答1:


This is because INPLACE_ADD only requests that the operation be done in place if possible; if the object is immutable or has not bothered to implement __iadd__, INPLACE_ADD falls back on regular, not-in-place addition. If the code was

t = [1, 2, (30)]
t[2] += (40,)

it would obviously be necessary to store the new tuple back into t[2], since the operation produces a new tuple instead of mutating the old one.




回答2:


That's because t[2] += [40] works like this:

temp = t[2]
temp += [40] # INPLACE_ADD
t[2] = temp  # STORE_SUBSCR

Python actually doesn't update the list in-place, the value is stored in a temporary variable first.

Proof:

>>> lst  = [[1], [2], [3]]
>>> def func():
...     lst[0] = [100]
...     return [40]
...
>>> lst[0] += func()
>>> lst
[[1, 40], [2], [3]]  # Not [[100, 40], [2], [3]]


来源:https://stackoverflow.com/questions/31039969/why-do-python-emit-store-substr-when-theres-already-an-inplace-add

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!