How does variable swapping work in Python (internally)

Python is a very high level language, a single Python instruction actually results in a lot of things going on.

The first thing that is necessary to understand that Python variables aren't the same as variables in lower level languages like C. They do not refer to a specific memory location.

In Python, think of variables more like tags that get attached (and moved to) an object.

When you say a = b, it means: "look up the object tagged with b, and then attach the tag a to that object". And yes, a = 42 is interpreted as "create an int object that represents the value 42, then attach the label a to it".

a, b = b, a uses what Python calls "tuple unpacking". Bascially, a, b = x is handled like

a = x[0]
b = x[1]

So the first instruction is: "find the object tagged with x. Now take the first element of that object, and attach the tag a to it." The second works similarly.

Now instead of x, we can specify any object, even create one. So what happens in a, b = b, a is this:

some_tuple = (b, a)
a = some_tuple[0]
b = some_tuple[1]

Or put in words: a, b = b, a is interpreted as: "create an tuple object for me. To get the first element, look up the object that has the b tag, the second element is the object with the tag a. Now, I want you to tag the first element of that tuple with a and the second one with b." Since our tuple was created with the object pointed to by b as first element, we effectively swapped the two tags around. a now is attached to the one b used to be attached to, and vice versa.

Remember, in Python: a = b never copies, it just moves a tag. This is why things like this happen:

a = [1, 2, 3]
b = a
a[0] = 42
print(b) # [42, 2, 3]; if it were a copy it would have stayed as [1, 2, 3]

Fun fact: if a and b are integers, you can also swap them in lower level languages by using xor:

a ^= b  # a is now old_a ^ old_b
b ^= a  # b is old_b ^ a = old_b ^ ( old_a ^ old_b) = old_b ^ old_a ^ old_b = old_b ^ old_b ^ old_a = 0 ^ old_a = old_a
a ^= b  # a is now (old_a ^ old_b) ^ old_a = old_a ^ old_a ^ old_b = 0 ^ old_b = old_b
/r/learnpython Thread