Friday Challenge #1
For the last five weeks I’ve been posting a weekly Python challenge on LinkedIn’s Python Developers Community. It is a bit of fun and a way to stretch the members and show them something a little surprising and/or interesting about Python.
Here is the first challenge. Before you continue reading, see if you can work out the answer yourself.
The question is: what is the output from the last line?
>>> a = [1, 2, 3]
>>> b = a
>>> a += [4]
>>> print(a, b)
[1, 2, 3, 4] [1, 2, 3, 4]
>>> a = 1, 2, 3
>>> b = a
>>> a += 4,
>>> print(a, b)
The possible answers are:
A. [1, 2, 3, 4] [1, 2, 3, 4]
B. Error
C. (1, 2, 3, 4) (1, 2, 3)
D. (1, 2, 3, 4) (1, 2, 3, 4)
E. Other
What do you think?
Note how the first four lines of code seem to be doing exactly the same as the second four lines of code. The difference is that the first set uses lists whilst the second set uses tuples.
a = [1, 2, 3]
b = a
a += [4]
print(a, b)
a = 1, 2, 3
b = a
a += 4,
print(a, b)
A few things to note about the right hand code:
- To create a tuple you don’t always need the round brackets. Round brackets are only needed when otherwise the code would be ambiguous. “a = 1, 2, 3” will create a tuple with 3 elements.
- To create a tuple you do need a comma. For instance “a = 4,” creates a tuple (note the comma after the 4). But “a = (4)” creates an integer. This is similar to “a = (1 + 3)”.
What about the third line, “a += [4]” and “a += 4,”?
“+=” is an in-place operation. The official documentation calls this an “augmented assignment statement”. Here is what it says:
“An augmented assignment expression like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. [….] when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.” (emphasis added by myself)
The left-hand version uses lists. Lists can be modified (they are ‘mutable’). If ‘a’ and ‘aa’ are both lists, then “a += aa” modifies ‘a’. It is equivalent to “a.extend(aa)”.
(in the left hand code) ‘a’ and ‘b’ referenced the same object. The object was changed, so they now both reference the new version of the object, which is [1, 2, 3, 4].
The right hand version uses tuples. Tuples cannot be modified (they are ‘immutable’). If ‘a’ and ‘aa’ are both tuples then “a += aa” cannot modify (the object referenced by) ‘a’. Instead a new object is created and the variable ‘a’ updated so it now references the new object.
(in the right hand code) ‘a’ and ‘b’ referenced the same code. ‘a’ was changed to reference the new object, (1, 2, 3 4). ‘b’ wasn’t changed and still references the old object, (1, 2, 3).
So the output from both versions is:
a = [1, 2, 3]
b = a
a += [4]
print(a, b)
[1, 2, 3, 4] [1, 2, 3, 4]
a = 1, 2, 3
b = a
a += 4,
print(a, b)
(1, 2, 3, 4) (1, 2, 3)
And finally, the answer is:
C. (1, 2, 3, 4) (1, 2, 3)
Well done if you got this yourself. And if not, hopefully you learned something new.