4

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?

ruohola
  • 21,987
  • 6
  • 62
  • 97
Prasun Parate
  • 85
  • 1
  • 9
  • 1
    Does this answer your question? [Is there a standardized method to swap two variables in Python?](https://stackoverflow.com/questions/14836228/is-there-a-standardized-method-to-swap-two-variables-in-python) – Mitch May 23 '20 at 18:10
  • see link for detailed answer [enter link description here](https://stackoverflow.com/questions/44462635/python-what-is-the-space-complexity-when-tuple-swap-is-used-in-bubble-sorting) – Ritika Gupta May 23 '20 at 18:11
  • under the hood python implements this by having a temporary variable, which by using tuple notation is not visible in this example – Nikos M. May 23 '20 at 18:14
  • @NikosM That's incorrect. – ruohola May 23 '20 at 18:17
  • @MitchelPaulin No, I didn't get that. – Prasun Parate May 23 '20 at 18:17

2 Answers2

8

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.

Nikos M.
  • 8,033
  • 4
  • 36
  • 43
  • +1 Nice answer! But I would like to know what you mean by Python stack. Aren't all objects created on the private heap? Where does stack come into the picture? – Niraj Raut May 16 '21 at 16:00
  • The virtual stack of the python machine, see source code, it is implemented as a stack of a virtual machine. In this sense – Nikos M. May 16 '21 at 18:01
  • What does "stack of a virtual machine" mean? – Niraj Raut May 16 '21 at 20:28
  • The python bytecode is interpreted and ran by a virtual machine implemented in C++ (CPython) as one can see in the linked source code. This virtual machine has or simulates a stack. This is what is meant – Nikos M. May 17 '21 at 13:31
4

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.

ruohola
  • 21,987
  • 6
  • 62
  • 97
  • Technicaly speaking `ROT_TWO` swaps the top 2 values of the python stack VM. The `ROT_TWO` implementation, code tcan be found on CPython's repository. In a sense the role of the 3rd variable for swapping is played by the top of the stack. – Nikos M. May 26 '20 at 13:46
  • @NikosM. `Technicaly speaking ROT_TWO swaps the top 2 values of the python stack` And does my post somehow conflict with this..? `In a sense the role of the 3rd variable for swapping is played by the top of the stack.` This doesn't make any sense. – ruohola May 26 '20 at 13:58
  • No my friend your post does not conflict with that. I am simply trying to point out that the top of the stack plays the role of the 3rd variable for swapping the values. Simple as that – Nikos M. May 26 '20 at 13:59
  • In fact I have upvoted your post, it is excellent! But out of curiosity I delved into the ROT_TWO implementation to see how it works. Thats all – Nikos M. May 26 '20 at 14:07
  • @NikosM. Oukkei – ruohola May 26 '20 at 14:12
  • Officialy here: https://github.com/python/cpython/blob/master/Python/ceval.c#L1535. As a matter of fact 4 memory locations are used for ROT_TWO implementation not even 3 (the minimum). Two stack locations and two variable locations. – Nikos M. May 26 '20 at 14:20
  • See my [complementary answer](https://stackoverflow.com/a/62038590/3591273) to yours – Nikos M. May 27 '20 at 08:29
  • @NikosM. Nice stuff :) – ruohola May 27 '20 at 08:47