CPython реализован как стековая машина . Если вы хотите точно увидеть, в каком порядке вычисляются подвыражения, может быть полезно разобрать их:
>>> from dis import dis
>>> dis('''
... available_items = {"health potion": 10, "cake of the cure": 5, "green elixir": 20, "strength sandwich": 25, "stamina grains": 15, "power stew": 30}
...
... health_points = 20
...
... health_points += available_items.pop("stamina grains")
... ''')
2 0 LOAD_CONST 0 (10)
2 LOAD_CONST 1 (5)
4 LOAD_CONST 2 (20)
6 LOAD_CONST 3 (25)
8 LOAD_CONST 4 (15)
10 LOAD_CONST 5 (30)
12 LOAD_CONST 6 (('health potion', 'cake of the cure', 'green elixir', 'strength sandwich', 'stamina grains', 'power stew'))
14 BUILD_CONST_KEY_MAP 6
16 STORE_NAME 0 (available_items)
4 18 LOAD_CONST 2 (20)
20 STORE_NAME 1 (health_points)
6 22 LOAD_NAME 1 (health_points)
24 LOAD_NAME 0 (available_items)
26 LOAD_METHOD 2 (pop)
28 LOAD_CONST 7 ('stamina grains')
30 CALL_METHOD 1
32 INPLACE_ADD
34 STORE_NAME 1 (health_points)
36 LOAD_CONST 8 (None)
38 RETURN_VALUE
В то время как подвыражения (в основном) оценивают слева направо, приоритет операторов и скобки могут изменить это. И назначение - это утверждение, а не выражение. Даже если +=
находится слева от .pop()
, вы можете видеть, что вызов происходит до назначения в скомпилированном байт-коде.
Обратите внимание, что вызов (pop)
помещает свое возвращаемое значение в стек по команде CALL_METHOD
, поэтому он может использоваться INPLACE_ADD
. В это время значение не указывается в dict, только в стеке, но ни в коем случае значение не было потеряно. И результат добавления доступен для инструкции STORE_NAME
после этого.