{"id":"references-copying","slug":"copying","title":"Copying a list","text":"When you want a second list that you can change on its own, you have to make a **copy**. The long way is a new empty list and a loop that appends each item to it:\n\n```python\noriginal = [3, 1, 2]\nduplicate = []\nfor item in original:\n    duplicate.append(item)\n\nduplicate.append(4)\nprint(original)\nprint(duplicate)\n```\n\n```output\n[3, 1, 2]\n[3, 1, 2, 4]\n```\n\nNow there are two lists, and changing one leaves the other alone. Python has three shorter ways to do the same, and each of them gives a new list with the same items:\n\n```pycon\n>>> original = [3, 1, 2]\n>>> a = original.copy()\n>>> b = original[:]\n>>> c = list(original)\n>>> a.append(4)\n>>> b[0] = 99\n>>> c.sort()\n>>> original\n[3, 1, 2]\n>>> a\n[3, 1, 2, 4]\n>>> b\n[99, 1, 2]\n>>> c\n[1, 2, 3]\n```\n\n- `copy()` is a list method that does just that.\n- `[:]` is a slice with no start and no end, so it takes every item. A slice is always a new list.\n- `list(...)` builds a new list from the items it's given, as it does with `range`.\n\nAll three work. `copy()` is the easiest to read, because it says what it does.\n\n### Copying a list of lists\n\nA copy holds the same items as the original. When those items are lists, as in a matrix, the copy holds references to the very same inner lists. The two outer lists are separate, but they share their rows:\n\n```python\nboard = [[\".\", \".\"], [\".\", \".\"]]\nsaved = board.copy()\n\nboard[0][0] = \"X\"\nboard.append([\"new\", \"row\"])\nprint(saved)\n```\n\n```output\n[['X', '.'], ['.', '.']]\n```\n\nThe new row went into `board` only, because the outer lists are separate. But the `\"X\"` went into a row that both lists share, so it shows up in `saved` too. To copy a matrix so that nothing is shared, copy each row as well:\n\n```python\nboard = [[\".\", \".\"], [\".\", \".\"]]\nsaved = []\nfor row in board:\n    saved.append(row.copy())\n\nboard[0][0] = \"X\"\nprint(board)\nprint(saved)\n```\n\n```output\n[['X', '.'], ['.', '.']]\n[['.', '.'], ['.', '.']]\n```\n","task":"The sale prices should be half of the normal prices, but the normal prices must stay as they are. Fill in the blank with a copy of `prices`, so the program prints:\n\n```\nNormal: [10, 25, 40]\nSale: [5, 12, 20]\n```\n","kind":"fill","seed":"prices = [10, 25, 40]\nsale_prices = [[prices.copy()‖prices[:]‖list(prices)]]\nfor i in range(len(sale_prices)):\n    sale_prices[i] = sale_prices[i] // 2\n\nprint(\"Normal:\", prices)\nprint(\"Sale:\", sale_prices)\n","solution":"prices = [10, 25, 40]\nsale_prices = prices.copy()\nfor i in range(len(sale_prices)):\n    sale_prices[i] = sale_prices[i] // 2\n\nprint(\"Normal:\", prices)\nprint(\"Sale:\", sale_prices)\n","hints":["`sale_prices = prices` wouldn't do: both names would refer to one list, and halving it would halve the normal prices too.","A copy is `prices.copy()`. (`prices[:]` and `list(prices)` work too.)"],"tests":[{"name":"Output","stdin":"","expect":"Normal: [10, 25, 40]\nSale: [5, 12, 20]","hidden":false}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"a = [1, 2, 3]\nb = a[:]\nc = a\nc.append(4)\nb.append(5)\nprint(a)\nprint(b)\nprint(len(c))\n","solution":"a = [1, 2, 3]\nb = a[:]\nc = a\nc.append(4)\nb.append(5)\nprint(a)\nprint(b)\nprint(len(c))\n","hints":["`b = a[:]` makes a new list, a copy. `c = a` makes a second name for the list `a` refers to.","So `c.append(4)` changes the list of `a`, and `b.append(5)` changes only the copy."],"tests":[{"name":"Output","stdin":"","expect":"[1, 2, 3, 4]\n[1, 2, 3, 5]\n4","hidden":false}],"require":[],"forbid":[],"lines":["[1, 2, 3, 4]","[1, 2, 3, 5]","4"]},{"task":"Write a function `copy_grid(grid)` that returns a copy of a matrix. Nothing may be shared between the copy and the original: after the copy is made, changes to the original's rows must not show up in the copy.\n\n```python\ngrid = [[1, 2], [3, 4]]\nsaved = copy_grid(grid)\ngrid[0][0] = 99\nprint(saved)\nprint(grid)\n```\n\n```\n[[1, 2], [3, 4]]\n[[99, 2], [3, 4]]\n```\n","kind":"code","seed":"def copy_grid(grid: list) -> list:\n    pass\n\n\nif __name__ == \"__main__\":\n    grid = [[1, 2], [3, 4]]\n    saved = copy_grid(grid)\n    grid[0][0] = 99\n    print(saved)\n    print(grid)\n","solution":"def copy_grid(grid: list) -> list:\n    result = []\n    for row in grid:\n        result.append(row.copy())\n    return result\n\n\nif __name__ == \"__main__\":\n    grid = [[1, 2], [3, 4]]\n    saved = copy_grid(grid)\n    grid[0][0] = 99\n    print(saved)\n    print(grid)\n","hints":["`grid.copy()` isn't enough: it makes a new outer list, but the rows in it are the same lists as in `grid`.","Make a new empty list, then go through the rows and append a copy of each row to it.","A copy of one row is `row.copy()`."],"tests":[{"name":"Test 1","stdin":"","call":"grid = [[1, 2], [3, 4]]\nsaved = copy_grid(grid)\ngrid[0][0] = 99\nprint(saved)\nprint(grid)\n","expect":"[[1, 2], [3, 4]]\n[[99, 2], [3, 4]]","hidden":false},{"name":"Test 2","stdin":"","call":"grid = [[\"a\"], [\"b\"], [\"c\"]]\nsaved = copy_grid(grid)\ngrid[2].append(\"d\")\ngrid.append([\"e\"])\nprint(saved)\n","expect":"[['a'], ['b'], ['c']]","hidden":true},{"name":"Test 3","stdin":"","call":"grid = [[5, 6, 7]]\nsaved = copy_grid(grid)\nsaved[0][1] = 0\nprint(grid)\nprint(saved)\n","expect":"[[5, 6, 7]]\n[[5, 0, 7]]","hidden":true}],"require":[],"forbid":[]}]}