Tip 89 Treat Variables as References
Pythonic Programming — by Dmitry Zinoviev (102 / 116)
👈 Parse with literal_eval() | TOC | Isolate Exceptions 👉
★★2.7, 3.4+ Unlike C/C++/Java variables, a Python variable always holds a reference (a pointer, if you come from C/Go) to an object, not the object itself. Failing to remember that may lead you to dreadful mistakes. Consider the following statement that attempts to initialize a 3-by-3 Tic-Tac-Toe board as a nested list of lists of spaces:
board = [[' '] * 3] * 3
print(board)=> [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
Now, let’s make a move, put a cross in the upper-left corner:
board[0][0] = 'x'
print(board)=> [['x', ' ', ' '], ['x', ' ', ' '], ['x', ' ', ' ']]
The results do not look right. You wanted to make one move but made three. References did it.
The list [’ ’] * 3 is a list of three references to a single-character string ’ ’. Strings in Python are immutable, and that is why it is safe to have multiple references to them.
The list [[’ ’] * 3] is a single-item list. The single item is a reference to that three-string list that I mentioned before. And now, you make three copies of that reference: [[’ ’] * 3] * 3. Naturally, all three refer to the same list. When you change that list through the assignment statement, the other two…