Вопрос. Может ли кто-нибудь объяснить вывод? Почему z
равно 2
во втором print()
?
Код:
x=1
y=2
x,y,z=x,x,y
print(y,x,y,z)
z,y,z=x,y,z
print(x,y,z)
Выход:
1 1 1 2
1 1 2
Вопрос. Может ли кто-нибудь объяснить вывод? Почему z
равно 2
во втором print()
?
Код:
x=1
y=2
x,y,z=x,x,y
print(y,x,y,z)
z,y,z=x,y,z
print(x,y,z)
Выход:
1 1 1 2
1 1 2
Назначение кортежа Python использует стек, поэтому предполагается, что x = 1 и y = 2:
x,y,z=x,x,y
абстрактно переводится как:
push x (value 1) on stack: top_of_stack(TOS) -> 1
push x (value 1) on stack: TOS -> 1, 1
push y (value 2) on stack: TOS -> 2, 1, 1
reverse top 3 stack entries: TOS -> 1, 1, 2
pop stack and store in x (x=1) TOS -> 1, 2
pop stack and store in y (y=1) TOS -> 2
pop stack and store in z (z=2) TOS -> empty
окончательный результат: x=1, y=1, z=2, следующая строка:
z,y,z=x,y,z
помещает x,y,z (1,1,2), затем загружает z=1, затем y=1, затем z=2 (перезаписывая z=1).
Вот собственно разборка с комментариями:
>>> dis.dis('x=1;y=2;x,y,z=x,x,y;z,y,z=x,y,z')
1 0 LOAD_CONST 0 (1) # load constant 1
2 STORE_NAME 0 (x) # assign to x
4 LOAD_CONST 1 (2) # load constant 2
6 STORE_NAME 1 (y) # assign to y
8 LOAD_NAME 0 (x) # push x on stack (1)
10 LOAD_NAME 0 (x) # push x again on stack (1)
12 LOAD_NAME 1 (y) # push y on stack (2)
14 ROT_THREE # two instructions reverse stack
16 ROT_TWO # .. 2,1,1 becomes 1,1,2
18 STORE_NAME 0 (x) # pop x=1
20 STORE_NAME 1 (y) # pop y=1
22 STORE_NAME 2 (z) # pop z=2
24 LOAD_NAME 0 (x) # push x (1)
26 LOAD_NAME 1 (y) # push y (1)
28 LOAD_NAME 2 (z) # push z (2)
30 ROT_THREE # reverse stack
32 ROT_TWO # 2,1,1 becomes 1,1,2
34 STORE_NAME 2 (z) # pop z=1 <---
36 STORE_NAME 1 (y) # pop y=1 \
38 STORE_NAME 2 (z) # pop z=2 (overwriting previous)
Вы также можете думать об этом более абстрактно как:
So:
x=1
y=2
x,y,z=x,x,y
Означает:
# x,y,z=1,1,2
x=1
y=1
z=2
Затем:
z,y,z=x,y,z
Означает:
# z,y,z = 1,1,2
z=1
y=1
z=2 # overwriting previous z=1
Это потому, что в Python вы можете объявлять и присваивать несколько значений переменных в одной строке слева направо.
x=1
y=2
x,y, ->z<- =x,x, ->y<- then again, assignments are read from left to right, y is 2 and is passed to z, therefore z is now 2.
print(y,x,y,z)
z,y,z=x,y,z
print(x,y,z)
Тот же пример, но короче:
a = 10
b = 99
a, b, c = a, b, b
Мы присваиваем:
10 to a
99 to b
Тогда соответственно a, b, c = 10, 99, 99
В той же заметке print принимает столько параметров, сколько вам нужно динамически.
Поэтому, чтобы перевести то, что происходит, это:
x, y, z = 1, 1, 2
print(1, 1, 1, 2)
В твоем случае:
print(y,x,y,z)
Содержит значение: 1, 1, 1, 2.
Это потому, что x и y содержат 1, тогда как значение z содержит значение 2, но y было напечатано два раза, поэтому это также могло произойти.
print(z, z, z, x, y, y, z)
Это выведет: (2, 2, 2, 1, 1, 1, 2)
После этого в вашем коде
z, x, y = 1, 1, 2
print(1, 1, 2)
Вы можете прочитать о кортежах в разделе руководства Кортежи и последовательности а>. В вашем коде кортежи создаются и распаковываются.
Например, до этого второго присваивания z
равно 2
.
z,y,z=x,y,z
Здесь python создал кортеж (1,1,2)
с правой стороны, а затем распаковал слева. Итак, z
переназначается на 1, y
переназначается на 1... но затем z
переназначается во второй раз на 2, перезаписывая первое назначение.
Когда вы пишете x,y,z
, вы создаете кортеж из объектов, на которые ссылаются эти переменные. Эти объекты теперь имеют дополнительную ссылку как из переменной, так и из кортежа. И как только этот кортеж создан, ему все равно, что произойдет с этими переменными. Он не помнит их, только то, на что они ссылались.
Сценарий с ходовыми комментариями
x=1
y=2
x,y,z=x,x,y # create tuple (1,1,2) from the right hand side x,x,y
# then unpack left hand side: x=1; y=1; z=2.
print(y,x,y,z)
z,y,z=x,y,z # create a tuple (1,1,2) from the right hand side x,y,z
# then unpack left hand side: z=1; y=1; z=1 (overwriting z)
print(x,y,z)
(1,1,2)
. Поскольку вы разместили ответ с ним, я оставлю вас ответить на него :-)
- person alani; 24.08.2020
В строке 3 вы устанавливаете z в y x,y,z=x,x,y
print
, а не первого. Ваш ответ не объясняет z,y,z=x,y,z
.
- person Sebastian Simon; 26.08.2020
z
вy
, а затем печатаетеz
вprint(y,x,y,z)
? - person possum   schedule 24.08.2020(1, 1, 2)
он распаковывает его по порядку вz,y,z
. Итак, сначала он выполняетz=1
, затемy=1
, а затемz=2
перезаписывает только что назначенное1
. - person alani   schedule 24.08.2020