{"id":"dictionaries-keys-and-values","slug":"keys-and-values","title":"What a dictionary can hold","text":"The values in a dictionary can be of any type: numbers, strings, lists, even other dictionaries. Keys are often strings, but numbers work just as well. Here the keys are numbers:\n\n```python\ndays = {1: \"Monday\", 2: \"Tuesday\", 3: \"Wednesday\"}\nfor number in range(1, 4):\n    print(number, days[number])\n```\n\n```output\n1 Monday\n2 Tuesday\n3 Wednesday\n```\n\nWith lists as values, each key can have many values. A list in a dictionary is changed like any other list:\n\n```python\ngrades = {\"Ada\": [9, 7], \"Max\": [6]}\ngrades[\"Max\"].append(8)\ngrades[\"Lin\"] = []\nprint(grades)\nprint(grades[\"Ada\"][0])\n```\n\n```output\n{'Ada': [9, 7], 'Max': [6, 8], 'Lin': []}\n9\n```\n\n`grades[\"Max\"]` is a list, and `.append(8)` changes that list inside the dictionary. `grades[\"Ada\"][0]` reads from left to right: the value of `\"Ada\"`, then the item at index 0 of that list.\n\n### One value per key\n\nA key is in a dictionary only once. Assigning to a key that's already there replaces its value. That's also how you update a value:\n\n```pycon\n>>> stock = {\"apples\": 5}\n>>> stock[\"apples\"] = 3\n>>> stock\n{'apples': 3}\n>>> stock[\"apples\"] += 10\n>>> stock[\"apples\"]\n13\n```\n\n`stock[\"apples\"] += 10` reads the old value, adds 10 and stores the result under the same key. A value, on the other hand, can be stored under many keys: in `{\"Ada\": 9, \"Max\": 9}`, both keys have the value 9.\n\nA loop can fill a dictionary, one key at a time:\n\n```python\nnames = [\"Ada\", \"Max\", \"Lin\"]\nseat_of = {}\nfor i in range(len(names)):\n    seat_of[names[i]] = i + 1\nprint(seat_of)\nprint(seat_of[\"Lin\"])\n```\n\n```output\n{'Ada': 1, 'Max': 2, 'Lin': 3}\n3\n```\n\n### Keys must not change\n\nA key must be immutable. Numbers, strings and Booleans work (and so do tuples, which the last module of this part shows). A list can't be a key, because it could change after it went into the dictionary:\n\n```python\nplaces = {}\nplaces[[60, 24]] = \"Helsinki\"\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 2, in <module>\n    places[[60, 24]] = \"Helsinki\"\n    ~~~~~~^^^^^^^^^^\nTypeError: cannot use 'list' as a dict key (unhashable type: 'list')\n```\n\nTo find a key fast, Python turns it into a number called a **hash**, and that number must never change. A list's contents can change, so a list is \"unhashable\". Values have no such rule.\n","task":"Write a function `word_lengths(words)` that returns a dictionary in which each word of the list is a key and its length is the value. For example, `word_lengths([\"sun\", \"moon\", \"sky\"])` returns `{'sun': 3, 'moon': 4, 'sky': 3}`. If a word is in the list twice, it's in the dictionary once.\n","kind":"code","seed":"def word_lengths(words: list) -> dict:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(word_lengths([\"sun\", \"moon\", \"sky\"]))\n","solution":"def word_lengths(words: list) -> dict:\n    lengths = {}\n    for word in words:\n        lengths[word] = len(word)\n    return lengths\n\n\nif __name__ == \"__main__\":\n    print(word_lengths([\"sun\", \"moon\", \"sky\"]))\n","hints":["Start with an empty dictionary, `lengths = {}`, and return it at the end.","Go through the words, and for each one store its length: `lengths[word] = len(word)`.","A word that comes again is stored under the same key, which just replaces the value with the same length."],"tests":[{"name":"word_lengths([\"sun\", \"moon\", \"sky\"])","stdin":"","call":"word_lengths([\"sun\", \"moon\", \"sky\"])\n","expect":"{'sun': 3, 'moon': 4, 'sky': 3}","hidden":false,"returns":true},{"name":"word_lengths([\"a\", \"python\", \"a\"])","stdin":"","call":"word_lengths([\"a\", \"python\", \"a\"])\n","expect":"{'a': 1, 'python': 6}","hidden":true,"returns":true},{"name":"word_lengths([])","stdin":"","call":"word_lengths([])\n","expect":"{}","hidden":true,"returns":true}],"require":[],"forbid":[],"more":[{"task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"scores = {\"Ada\": 3, \"Max\": 5}\nscores[\"Ada\"] = 7\nscores[\"Lin\"] = scores[\"Max\"]\nscores[\"Max\"] += 1\nprint(scores)\nprint(len(scores))\n","solution":"scores = {\"Ada\": 3, \"Max\": 5}\nscores[\"Ada\"] = 7\nscores[\"Lin\"] = scores[\"Max\"]\nscores[\"Max\"] += 1\nprint(scores)\nprint(len(scores))\n","hints":["Assigning to a key that's already there replaces its value, so `\"Ada\"` stays where it was with a new value.","`scores[\"Lin\"] = scores[\"Max\"]` adds a new key with Max's value at that moment, 5.","`scores[\"Max\"] += 1` changes only Max's value."],"tests":[{"name":"Output","stdin":"","expect":"{'Ada': 7, 'Max': 6, 'Lin': 5}\n3","hidden":false}],"require":[],"forbid":[],"lines":["{'Ada': 7, 'Max': 6, 'Lin': 5}","3"]},{"task":"Write a function `divisor_table(n)` that returns a dictionary whose keys are the numbers from 1 to `n`. The value of each key is a list of the numbers that divide it evenly, from smallest to largest.\n\nFor example, `divisor_table(4)` returns `{1: [1], 2: [1, 2], 3: [1, 3], 4: [1, 2, 4]}`.\n","kind":"code","seed":"def divisor_table(n: int) -> dict:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(divisor_table(4))\n","solution":"def divisor_table(n: int) -> dict:\n    table = {}\n    for number in range(1, n + 1):\n        divisors = []\n        for candidate in range(1, number + 1):\n            if number % candidate == 0:\n                divisors.append(candidate)\n        table[number] = divisors\n    return table\n\n\nif __name__ == \"__main__\":\n    print(divisor_table(4))\n","hints":["Go through the numbers from 1 to `n` with `range(1, n + 1)`. Each one becomes a key.","For one number, build a list of its divisors: try every candidate from 1 to the number itself, and keep those with `number % candidate == 0`.","Store the list as the value: `table[number] = divisors`."],"tests":[{"name":"divisor_table(4)","stdin":"","call":"divisor_table(4)\n","expect":"{1: [1], 2: [1, 2], 3: [1, 3], 4: [1, 2, 4]}","hidden":false,"returns":true},{"name":"divisor_table(1)","stdin":"","call":"divisor_table(1)\n","expect":"{1: [1]}","hidden":true,"returns":true},{"name":"divisor_table(12)","stdin":"","call":"divisor_table(12)\n","expect":"{1: [1], 2: [1, 2], 3: [1, 3], 4: [1, 2, 4], 5: [1, 5], 6: [1, 2, 3, 6], 7: [1, 7], 8: [1, 2, 4, 8], 9: [1, 3, 9], 10: [1, 2, 5, 10], 11: [1, 11], 12: [1, 2, 3, 4, 6, 12]}","hidden":true,"returns":true}],"require":[],"forbid":[]}]}