Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How swapping variables is implemented in Python?

How does the below code work in Python:

a = input()
b = input()
a, b = b, a  # STATEMENT 1
print(a, b)

Does the statement 1 create a third variable in Python heap memory space to swap the two numbers or does it use some algorithm to do the swap?

like image 773
Prasun Avatar asked Sep 06 '25 03:09

Prasun


2 Answers

ruohola did a good job in providing the translated bytecode of the python code.

I am duplicating here for reference:

Python code:

a = input()
b = input()
a, b = b, a  # STATEMENT 1
print(a, b)

Bytecode:

 2           0 LOAD_NAME                0 (input)
             2 CALL_FUNCTION            0
             4 STORE_NAME               1 (a)

 3           6 LOAD_NAME                0 (input)
             8 CALL_FUNCTION            0
            10 STORE_NAME               2 (b)

 4          12 LOAD_NAME                2 (b)
            14 LOAD_NAME                1 (a)
            16 ROT_TWO                  # swapping done here
            18 STORE_NAME               1 (a)
            20 STORE_NAME               2 (b)
            22 LOAD_CONST               0 (None)
            24 RETURN_VALUE

ROT_TWO operation swaps the top 2 values of the python stack. So what do we actually have so far:

Python swaps the 2 values by calling a swap (ROT_TWO) subroutine.

If this is how far you want to go and it answers your question it is fine. However for those who want to go deeper and see how this swap (ROT_TWO) subroutine works, here is the official CPython implementation:

#define TOP()             (stack_pointer[-1])
#define SECOND()          (stack_pointer[-2])
#define SET_TOP(v)        (stack_pointer[-1] = (v))
#define SET_SECOND(v)     (stack_pointer[-2] = (v))
/*..*/
case TARGET(ROT_TWO): {
   PyObject *top = TOP();
   PyObject *second = SECOND();
   SET_TOP(second);
   SET_SECOND(top);
   FAST_DISPATCH();
}

Or in other words the implementation of ROT_TWO actually performs the following steps (a,b are the top 2 values of the stack):

x1 = a
x2 = b
a = x2
b = x1

So the implementation uses auxiliary temporary locations (x1, x2) and in fact it uses 2 auxilliary memory locations instead of the minimum 1 auxiliary location to swap two values that a more memory-efficient implementation would do:

x = a
a = b
b = x

Under the current computing model, swapping two values can be done only in so many different ways and does not happen magically:

  1. Using auxilliary temporary storage
  2. Employing a series of XOR (or similar arithmetic) operations

So to sum it up, Python under the hood indeed uses auxilliary temporary locations in order to swap the two values.

like image 134
Nikos M. Avatar answered Sep 07 '25 19:09

Nikos M.


It's a simple bytecode operation which doesn't need any intermediate variables to do the swap. See this demo:

import dis

code = '''
a = input()
b = input()
a, b = b, a
'''

dis.dis(code)

Output:

 2           0 LOAD_NAME                0 (input)
             2 CALL_FUNCTION            0
             4 STORE_NAME               1 (a)

 3           6 LOAD_NAME                0 (input)
             8 CALL_FUNCTION            0
            10 STORE_NAME               2 (b)

 4          12 LOAD_NAME                2 (b)
            14 LOAD_NAME                1 (a)
            16 ROT_TWO
            18 STORE_NAME               1 (a)
            20 STORE_NAME               2 (b)
            22 LOAD_CONST               0 (None)
            24 RETURN_VALUE

Note: Like bytecode as a whole, this is of course just an implementation detail of CPython.

like image 23
ruohola Avatar answered Sep 07 '25 21:09

ruohola