Python Arena
Step 1 of 4

Two names for one list

Up to now it has been fine to say that scores = [7, 9] puts a list in the variable scores. For lists, that way of thinking leads you astray. A variable doesn't hold the list itself: it holds a reference to it, which tells Python where the list is in the computer's memory. Think of the list as a house, and of the reference as the house's address written on a note.

Most of the time the difference doesn't matter. It matters as soon as two variables refer to the same list:

In the Python interpreter
>>> todo = ["wash", "cook"]
>>> today = todo
>>> today.append("shop")
>>> today[0] = "rest"
>>> todo
['rest', 'cook', 'shop']

today = todo doesn't copy the list. It copies the reference, the address, so todo and today are now two names for one and the same list. A change made through either name changes that one list, and both names see it. In a program this can be a surprise:

weekday_songs = ["Intro", "Rain", "Comets"]
weekend_songs = weekday_songs
weekend_songs.append("Party Time")

print("Weekdays:", weekday_songs)
print("Weekend:", weekend_songs)
Output
Weekdays: ['Intro', 'Rain', 'Comets', 'Party Time']
Weekend: ['Intro', 'Rain', 'Comets', 'Party Time']

Numbers and strings can't change

Why doesn't the same happen with numbers?

In the Python interpreter
>>> x = 5
>>> y = x
>>> y += 1
>>> x
5
>>> y
6

Numbers, strings and Booleans are immutable: nothing can change them. y += 1 doesn't change the number 5. It makes a new number, 6, and points y at it, while x still refers to 5. String methods work the same way: upper gives a new string and leaves the old one as it was. Lists are mutable: append, sort, remove, pop and assigning to an index all change the list itself, and every name that refers to it sees the change.

Giving a variable a new value is different from changing the list it refers to:

In the Python interpreter
>>> todo = ["wash", "cook"]
>>> today = todo
>>> today = ["sleep"]
>>> todo
['wash', 'cook']

today = ["sleep"] points today at a new list. The old list doesn't change, and todo still refers to it.

References inside lists

A matrix is a list that holds references to its rows. Taking a row out of a matrix gives you another name for that row, not a copy of it:

seats = [["free", "free"], ["free", "taken"]]
first_row = seats[0]
first_row[1] = "taken"
print(seats)
Output
[['free', 'taken'], ['free', 'taken']]

That's why row[j] = ... inside a loop over a matrix changes the matrix: row refers to one of its rows. But number *= 10 on a number taken from a row only points the variable number at a new number.

Your task

Challenge 1 of 3

What does this program print? Type each line it prints.

Challenge 2

The program should print the guests in the order they arrived and, below that, in alphabetical order. But both lines come out sorted:

Arrived: ['Lee', 'Ada', 'Max']
Sorted: ['Ada', 'Lee', 'Max']

Fix it so it prints the output above. Keep both variables.

Challenge 3

What does this program print? Type each line it prints.