{"id":"dictionaries-removing","slug":"removing","title":"Removing keys","text":"`del` removes a key and its value from a dictionary:\n\n```python\nlockers = {\"Ada\": 12, \"Max\": 7, \"Lin\": 3}\ndel lockers[\"Max\"]\nprint(lockers)\n```\n\n```output\n{'Ada': 12, 'Lin': 3}\n```\n\nRemoving a key that isn't there stops the program with a `KeyError`, just like reading one. When you aren't sure the key is there, check with `in` first:\n\n```python\nlockers = {\"Ada\": 12, \"Lin\": 3}\nname = \"Max\"\nif name in lockers:\n    del lockers[name]\n    print(name, \"gave back the key\")\nelse:\n    print(name, \"has no locker\")\n```\n\n```output\nMax has no locker\n```\n\n### pop\n\nThe method `pop` removes a key too, and it returns the key's value, which is handy when you still need it:\n\n```pycon\n>>> lockers = {\"Ada\": 12, \"Lin\": 3}\n>>> freed = lockers.pop(\"Ada\")\n>>> freed\n12\n>>> lockers\n{'Lin': 3}\n>>> print(lockers.pop(\"Max\", None))\nNone\n```\n\nGiven a second argument, `pop` doesn't stop at a missing key: it returns the second argument instead. `None`, Python's \"no value\", is a common choice. To check whether a value is `None`, write `is None`:\n\n```python\nlockers = {\"Ada\": 12, \"Lin\": 3}\nfreed = lockers.pop(\"Max\", None)\nif freed is None:\n    print(\"Max has no locker\")\nelse:\n    print(\"Locker\", freed, \"is free\")\n```\n\n```output\nMax has no locker\n```\n\n### Not while looping over it\n\nRemoving keys inside a `for` loop over the same dictionary stops the program:\n\n```python\nstock = {\"apples\": 5, \"pears\": 0, \"plums\": 0}\nfor fruit in stock:\n    if stock[fruit] == 0:\n        del stock[fruit]\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 2, in <module>\n    for fruit in stock:\n                 ^^^^^\nRuntimeError: dictionary changed size during iteration\n```\n\nThe loop can't keep its place in a dictionary that changes size under it. Loop over a list of the keys instead. `list(stock)` makes one, and that list stays as it is when the dictionary changes:\n\n```python\nstock = {\"apples\": 5, \"pears\": 0, \"plums\": 0}\nfor fruit in list(stock):\n    if stock[fruit] == 0:\n        del stock[fruit]\nprint(stock)\n```\n\n```output\n{'apples': 5}\n```\n\nTo empty a whole dictionary in one go, use the method `clear()`: `stock.clear()`.\n\nLike a list, a dictionary given to a function is passed as a reference. A function can add, change and remove the keys of the caller's dictionary.\n","task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"stock = {\"apples\": 5, \"pears\": 2, \"plums\": 7}\ndel stock[\"pears\"]\nsold = stock.pop(\"plums\")\nprint(stock)\nprint(sold)\nprint(stock.pop(\"kiwis\", 0))\nprint(len(stock))\n","solution":"stock = {\"apples\": 5, \"pears\": 2, \"plums\": 7}\ndel stock[\"pears\"]\nsold = stock.pop(\"plums\")\nprint(stock)\nprint(sold)\nprint(stock.pop(\"kiwis\", 0))\nprint(len(stock))\n","hints":["`del` removes the pears. `pop` removes the plums and returns their value.","`\"kiwis\"` isn't a key, so `pop` returns its second argument instead of stopping.","After both removals, one key is left."],"tests":[{"name":"Output","stdin":"","expect":"{'apples': 5}\n7\n0\n1","hidden":false}],"require":[],"forbid":[],"lines":["{'apples': 5}","7","0","1"],"more":[{"task":"Write a function `remove_below(scores, limit)` that removes from the dictionary it's given every name whose score is below `limit`. It changes the dictionary and returns nothing.\n\n```python\nscores = {\"Ada\": 9, \"Max\": 4, \"Lin\": 6, \"Kim\": 2}\nremove_below(scores, 5)\nprint(scores)\n```\n\n```\n{'Ada': 9, 'Lin': 6}\n```\n","kind":"code","seed":"def remove_below(scores: dict, limit: int):\n    pass\n\n\nif __name__ == \"__main__\":\n    scores = {\"Ada\": 9, \"Max\": 4, \"Lin\": 6, \"Kim\": 2}\n    remove_below(scores, 5)\n    print(scores)\n","solution":"def remove_below(scores: dict, limit: int):\n    for name in list(scores):\n        if scores[name] < limit:\n            del scores[name]\n\n\nif __name__ == \"__main__\":\n    scores = {\"Ada\": 9, \"Max\": 4, \"Lin\": 6, \"Kim\": 2}\n    remove_below(scores, 5)\n    print(scores)\n","hints":["Go through the names and remove each one whose score is below `limit` with `del scores[name]`.","Removing keys while looping over the dictionary itself stops with a `RuntimeError`. Loop over `list(scores)`, a list of the keys, instead."],"tests":[{"name":"Test 1","stdin":"","call":"scores = {\"Ada\": 9, \"Max\": 4, \"Lin\": 6, \"Kim\": 2}\nremove_below(scores, 5)\nprint(scores)\n","expect":"{'Ada': 9, 'Lin': 6}","hidden":false},{"name":"Test 2","stdin":"","call":"scores = {\"Bo\": 1, \"Cy\": 2}\nremove_below(scores, 10)\nprint(scores)\n","expect":"{}","hidden":true},{"name":"Test 3","stdin":"","call":"scores = {\"Bo\": 5, \"Cy\": 7, \"Di\": 4}\nremove_below(scores, 5)\nprint(scores)\n","expect":"{'Bo': 5, 'Cy': 7}","hidden":true}],"require":[],"forbid":[]},{"task":"Write a function `rename_key(data, old, new)` that moves the value of the key `old` to the key `new` in the dictionary it's given, so that `old` is no longer a key. If `old` isn't in the dictionary, the function changes nothing. It returns nothing.\n\n```python\nages = {\"Ada\": 36, \"Max\": 41}\nrename_key(ages, \"Max\", \"Maxine\")\nprint(ages)\n```\n\n```\n{'Ada': 36, 'Maxine': 41}\n```\n","kind":"code","seed":"def rename_key(data: dict, old, new):\n    pass\n\n\nif __name__ == \"__main__\":\n    ages = {\"Ada\": 36, \"Max\": 41}\n    rename_key(ages, \"Max\", \"Maxine\")\n    print(ages)\n","solution":"def rename_key(data: dict, old, new):\n    if old in data:\n        data[new] = data.pop(old)\n\n\nif __name__ == \"__main__\":\n    ages = {\"Ada\": 36, \"Max\": 41}\n    rename_key(ages, \"Max\", \"Maxine\")\n    print(ages)\n","hints":["`data.pop(old)` removes the old key and gives you its value, ready to store under the new key.","Check `if old in data:` first, so a missing key doesn't stop the program.","Inside the `if`, one line does it: `data[new] = data.pop(old)`."],"tests":[{"name":"Test 1","stdin":"","call":"ages = {\"Ada\": 36, \"Max\": 41}\nrename_key(ages, \"Max\", \"Maxine\")\nprint(ages)\n","expect":"{'Ada': 36, 'Maxine': 41}","hidden":false},{"name":"Test 2","stdin":"","call":"ages = {\"Ada\": 36}\nrename_key(ages, \"Bo\", \"Bob\")\nprint(ages)\n","expect":"{'Ada': 36}","hidden":true},{"name":"Test 3","stdin":"","call":"codes = {1: \"one\", 2: \"two\", 3: \"three\"}\nrename_key(codes, 1, 10)\nprint(codes)\n","expect":"{2: 'two', 3: 'three', 10: 'one'}","hidden":true}],"require":[],"forbid":[]}]}