Assignment operation Python

I am new to Python and the following question is so difficult for me to understand.

a,b,c=1,2,3
a,b,c=c,a,b=b,a,c=c,b,a
print(a,b,c)

The output of this is -

(2,3,1)

but I don't understand why it isn't -

(3,2,1)

Upvotes: 2

Views: 2505

Answers (3)

Cohan
Cohan

Reputation: 4544

As norok indicated, storage and loading happen from different directions. If we take the following code we can see what python is doing under the hood.

import dis

def foo():
    a, b, c = 1, 2, 3
    a, b, c = c, a, b = b, a, c = c, b, a

dis.dis(foo)

Below you see the bytecode. To the right of the comments, you see the values for variables a, b, and c as well as the memory stack at the end of the operation. You'll see the DUP_TOP command negate the assignments at various steps so only the first load and last store appear to do anything. This would also explain why a, b, c = a, a, a = b, b, b = c, c, c = b, a, c = c, b, a still evaluates to (2, 3, 1).

                                                      # a b c stack

4           0 LOAD_CONST               4 ((1, 2, 3))  # - - - [(1, 2, 3)]
            3 UNPACK_SEQUENCE          3              # - - - [1, 2, 3]
            6 STORE_FAST               0 (a)          # 1 - - [2, 3]
            9 STORE_FAST               1 (b)          # 1 2 - [3]
           12 STORE_FAST               2 (c)          # 1 2 3 []

5          15 LOAD_FAST                2 (c)          # 1 2 3 [3]
           18 LOAD_FAST                1 (b)          # 1 2 3 [3, 2]
           21 LOAD_FAST                0 (a)          # 1 2 3 [3, 2, 1]
           24 BUILD_TUPLE              3              # 1 2 3 [(3, 2, 1)]
           27 DUP_TOP                                 # 1 2 3 [(3, 2, 1), (3, 2, 1)]
           28 UNPACK_SEQUENCE          3              # 1 2 3 [3, 2, 1, (3, 2, 1)]
           31 STORE_FAST               0 (a)          # 3 2 3 [2, 1, (3, 2, 1)]
           34 STORE_FAST               1 (b)          # 3 2 3 [1, (3, 2, 1)]
           37 STORE_FAST               2 (c)          # 3 2 1 [(3, 2, 1)]
           40 DUP_TOP                                 # 3 2 1 [(3, 2, 1), (3, 2, 1)]
           41 UNPACK_SEQUENCE          3              # 3 2 1 [3, 2, 1, (3, 2, 1)]
           44 STORE_FAST               2 (c)          # 3 2 3 [2, 1, (3, 2, 1)]
           47 STORE_FAST               0 (a)          # 2 2 3 [1, (3, 2, 1)]
           50 STORE_FAST               1 (b)          # 2 1 3 [(3, 2, 1)]
           53 UNPACK_SEQUENCE          3              # 2 1 3 [3, 2, 1]
           56 STORE_FAST               1 (b)          # 2 3 3 [2, 1]
           59 STORE_FAST               0 (a)          # 2 3 3 [1]
           62 STORE_FAST               2 (c)          # 2 3 1 []

Upvotes: 1

norok2
norok2

Reputation: 26886

What you think it is happening

a, b, c = 1, 2, 3
b, a, c = c, b, a
print(a, b, c)
# 2, 3, 1
c, a, b = b, a, c
print(a, b, c)
# 2, 1, 3
a, b, c = c, a, b
print(a, b, c)
# 3, 2, 1

What is actually happening

a, b, c = 1, 2, 3
# a, b, c = c, a, b = b, a, c = c, b, a
temp = c, b, a
a, b, c = temp
print(a, b, c)
# 3 2 1
c, a, b = temp
print(a, b, c)
# 2 1 3
b, a, c = temp
print(a, b, c)
# 2 3 1

Basically: the loading happen from the right according to c, b, a, while the storing happen from left to right.

This is evidenced by disassembling the expression:

import dis


def chained_assign():
    a, b, c = 1, 2, 3
    a, b, c = c, a, b = b, a, c = c, b, a
    return a, b, c


dis.dis(chained_assign)

Output:

  5           0 LOAD_CONST               4 ((1, 2, 3))
              2 UNPACK_SEQUENCE          3
              4 STORE_FAST               0 (a)
              6 STORE_FAST               1 (b)
              8 STORE_FAST               2 (c)

  6          10 LOAD_FAST                2 (c)
             12 LOAD_FAST                1 (b)
             14 LOAD_FAST                0 (a)
             16 BUILD_TUPLE              3
             18 DUP_TOP
             20 UNPACK_SEQUENCE          3
             22 STORE_FAST               0 (a)
             24 STORE_FAST               1 (b)
             26 STORE_FAST               2 (c)
             28 DUP_TOP
             30 UNPACK_SEQUENCE          3
             32 STORE_FAST               2 (c)
             34 STORE_FAST               0 (a)
             36 STORE_FAST               1 (b)
             38 UNPACK_SEQUENCE          3
             40 STORE_FAST               1 (b)
             42 STORE_FAST               0 (a)
             44 STORE_FAST               2 (c)

  7          46 LOAD_FAST                0 (a)
             48 LOAD_FAST                1 (b)
             50 LOAD_FAST                2 (c)
             52 BUILD_TUPLE              3
             54 RETURN_VALUE

Notice the order of the STORE_FAST and LOAD_FAST instructions from line 6.

Additional discussion here:

Upvotes: 4

Rudra shah
Rudra shah

Reputation: 841

It is because, when you write like this it means -: a = c = b = c value of a becomes c, the value of c becomes b and the value of b becomes c. so in last the change in the variable is taking place for b not a.

so the output would be-:

2 3 1

not-:

3 2 1

Upvotes: 1

Related Questions