问题
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