Все с правой стороны оценивается первым.Вы можете использовать disasembler байт-кода Python, чтобы увидеть, что происходит:
>>> import dis
>>> dis.dis('x, y = x + 2, print(x)')
1 0 LOAD_NAME 0 (x)
2 LOAD_CONST 0 (2)
4 BINARY_ADD
6 LOAD_NAME 1 (print)
8 LOAD_NAME 0 (x)
10 CALL_FUNCTION 1
12 ROT_TWO
14 STORE_NAME 0 (x)
16 STORE_NAME 2 (y)
18 LOAD_CONST 1 (None)
20 RETURN_VALUE
>>>
Примечание, x + 2
и print(x)
оцениваются сначала .BINARY_ADD и CALL_FUNCTION появляются перед двумя STORE_NAME
s.
Обратите внимание, вы можете думать об этом как об эквивалентном построении кортежа:
temp = (x + 2, print(x))
, а затем просто:
x, y = temp
Тем не менее, обратите внимание, что в соответствии с disasembler фактический промежуточный кортеж не создается.Стек вызовов используется для хранения промежуточных значений.Это оптимизация компилятора.Однако оптимизация не работает для кортежей, длина которых превышает 3, поэтому, используя 4, вы увидите, что промежуточный кортеж создает:
>>> dis.dis('foo, bar, baz, bang = bang, baz, bar, foo')
1 0 LOAD_NAME 0 (bang)
2 LOAD_NAME 1 (baz)
4 LOAD_NAME 2 (bar)
6 LOAD_NAME 3 (foo)
8 BUILD_TUPLE 4
10 UNPACK_SEQUENCE 4
12 STORE_NAME 3 (foo)
14 STORE_NAME 2 (bar)
16 STORE_NAME 1 (baz)
18 STORE_NAME 0 (bang)
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
>>>
Обратите внимание на BUILD_TUPLE
и UNPACK_SEQUENCE
, то естьОбщий способ, что распаковка работает в Python.Просто компилятор оптимизирует общие случаи двух или трех с помощью операционных кодов ROT_TWO и ROT_THREE.
Обратите внимание: поскольку правая часть вычисляется первой, это позволяет работать идиоме подкачки Python!
x, y = y, x
Если бы это было эквивалентно:
x = y
y = x
Вы бы потеряли значение для x вместо замены!