{"id":"references-same-list","slug":"same-list","title":"Two names for one list","text":"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.\n\nMost of the time the difference doesn't matter. It matters as soon as two variables refer to the same list:\n\n```pycon\n>>> todo = [\"wash\", \"cook\"]\n>>> today = todo\n>>> today.append(\"shop\")\n>>> today[0] = \"rest\"\n>>> todo\n['rest', 'cook', 'shop']\n```\n\n`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:\n\n```python\nweekday_songs = [\"Intro\", \"Rain\", \"Comets\"]\nweekend_songs = weekday_songs\nweekend_songs.append(\"Party Time\")\n\nprint(\"Weekdays:\", weekday_songs)\nprint(\"Weekend:\", weekend_songs)\n```\n\n```output\nWeekdays: ['Intro', 'Rain', 'Comets', 'Party Time']\nWeekend: ['Intro', 'Rain', 'Comets', 'Party Time']\n```\n\n### Numbers and strings can't change\n\nWhy doesn't the same happen with numbers?\n\n```pycon\n>>> x = 5\n>>> y = x\n>>> y += 1\n>>> x\n5\n>>> y\n6\n```\n\nNumbers, 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.\n\nGiving a variable a new value is different from changing the list it refers to:\n\n```pycon\n>>> todo = [\"wash\", \"cook\"]\n>>> today = todo\n>>> today = [\"sleep\"]\n>>> todo\n['wash', 'cook']\n```\n\n`today = [\"sleep\"]` points `today` at a new list. The old list doesn't change, and `todo` still refers to it.\n\n### References inside lists\n\nA 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:\n\n```python\nseats = [[\"free\", \"free\"], [\"free\", \"taken\"]]\nfirst_row = seats[0]\nfirst_row[1] = \"taken\"\nprint(seats)\n```\n\n```output\n[['free', 'taken'], ['free', 'taken']]\n```\n\nThat'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.\n","task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"team = [\"Ana\", \"Ben\"]\nplayers = team\nplayers.append(\"Cleo\")\nprint(team)\nplayers = [\"Dev\"]\nprint(team)\nprint(players)\n","solution":"team = [\"Ana\", \"Ben\"]\nplayers = team\nplayers.append(\"Cleo\")\nprint(team)\nplayers = [\"Dev\"]\nprint(team)\nprint(players)\n","hints":["`players = team` doesn't copy the list: both names refer to the same list.","So `players.append(\"Cleo\")` changes the list that `team` refers to, too.","`players = [\"Dev\"]` points `players` at a new list, and `team` keeps the old one."],"tests":[{"name":"Output","stdin":"","expect":"['Ana', 'Ben', 'Cleo']\n['Ana', 'Ben', 'Cleo']\n['Dev']","hidden":false}],"require":[],"forbid":[],"lines":["['Ana', 'Ben', 'Cleo']","['Ana', 'Ben', 'Cleo']","['Dev']"],"more":[{"task":"The program should print the guests in the order they arrived and, below that, in alphabetical order. But both lines come out sorted:\n\n```\nArrived: ['Lee', 'Ada', 'Max']\nSorted: ['Ada', 'Lee', 'Max']\n```\n\nFix it so it prints the output above. Keep both variables.\n","kind":"code","seed":"arrived = [\"Lee\", \"Ada\", \"Max\"]\nalphabetical = arrived\nalphabetical.sort()\n\nprint(\"Arrived:\", arrived)\nprint(\"Sorted:\", alphabetical)\n","solution":"arrived = [\"Lee\", \"Ada\", \"Max\"]\nalphabetical = sorted(arrived)\n\nprint(\"Arrived:\", arrived)\nprint(\"Sorted:\", alphabetical)\n","hints":["`alphabetical = arrived` makes two names for one list, so sorting it sorts the guests' arrival order too.","`sorted(arrived)` gives a new, sorted list and leaves `arrived` as it was. Use it instead of the two lines with `=` and `sort`."],"tests":[{"name":"Output","stdin":"","expect":"Arrived: ['Lee', 'Ada', 'Max']\nSorted: ['Ada', 'Lee', 'Max']","hidden":false}],"require":[{"pattern":"\\balphabetical\\s*=","message":"Keep the variable `alphabetical` for the sorted list."}],"forbid":[]},{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"grid = [[0, 0], [0, 0]]\nrow = grid[1]\nrow[0] = 5\nvalue = grid[0][1]\nvalue = 9\nprint(grid)\nprint(row)\n","solution":"grid = [[0, 0], [0, 0]]\nrow = grid[1]\nrow[0] = 5\nvalue = grid[0][1]\nvalue = 9\nprint(grid)\nprint(row)\n","hints":["`row = grid[1]` gives a second name to the second row of the grid, so `row[0] = 5` changes the grid.","`value = grid[0][1]` gives `value` the number 0. Then `value = 9` points the variable at a new number; the grid doesn't change."],"tests":[{"name":"Output","stdin":"","expect":"[[0, 0], [5, 0]]\n[5, 0]","hidden":false}],"require":[],"forbid":[],"lines":["[[0, 0], [5, 0]]","[5, 0]"]}]}