{"id":"tuples-unpacking","slug":"without-parentheses","title":"Tuples without parentheses","text":"It's the commas that make a tuple, not the parentheses. Values separated by commas are a tuple even without them:\n\n```pycon\n>>> numbers = 1, 2, 3\n>>> numbers\n(1, 2, 3)\n>>> single = 5,\n>>> single\n(5,)\n```\n\nA tuple of one value needs its comma too: `(5)` is just the number 5 in parentheses.\n\n### Returning several values\n\nA function returns one value, but that value can be a tuple. So a function can give back several values by returning them separated by commas:\n\n```python\ndef to_minutes(total_seconds: int) -> tuple:\n    return total_seconds // 60, total_seconds % 60\n\n\nresult = to_minutes(135)\nprint(result)\n\nminutes, seconds = to_minutes(135)\nprint(f\"{minutes} min {seconds} s\")\n```\n\n```output\n(2, 15)\n2 min 15 s\n```\n\n### Unpacking\n\n`minutes, seconds = to_minutes(135)` is called **unpacking**: the values of the tuple on the right go into the variables on the left, in order. The number of variables has to match the number of values:\n\n```python\npoint = (3, 7, 1)\nx, y = point\n```\n\n```crash\nTraceback (most recent call last):\n  File \"main.py\", line 2, in <module>\n    x, y = point\n    ^^^^\nValueError: too many values to unpack (expected 2, got 3)\n```\n\nUnpacking works in a `for` loop too. A loop over a list of tuples can unpack each one right away. That's what happens in `for key, value in d.items()`: `items()` gives each pair of the dictionary as a tuple.\n\n```python\npioneers = [(\"Ada\", 1815), (\"Alan\", 1912), (\"Grace\", 1906)]\nfor name, year in pioneers:\n    print(name, year)\n\nages = {\"Ada\": 36, \"Max\": 41}\nprint(list(ages.items()))\n```\n\n```output\nAda 1815\nAlan 1912\nGrace 1906\n[('Ada', 36), ('Max', 41)]\n```\n\n### Swapping two values\n\nTo swap the values of two variables, you would normally need a helper variable, because the first assignment overwrites one of the values:\n\n```python\nhelper = a\na = b\nb = helper\n```\n\nWith a tuple it takes one line. Python first makes a tuple of the values on the right, and only then unpacks it into the variables on the left:\n\n```python\na = 1\nb = 2\na, b = b, a\nprint(a, b)\n```\n\n```output\n2 1\n```\n","task":"Fill in the blank so the loop unpacks each tuple into the variables `name` and `score`, and the program prints:\n\n```\nAda: 92 points\nMax: 78 points\nLin: 85 points\n```\n","kind":"fill","seed":"results = [(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)]\nfor [[name, score‖(name, score)]] in results:\n    print(f\"{name}: {score} points\")\n","solution":"results = [(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)]\nfor name, score in results:\n    print(f\"{name}: {score} points\")\n","hints":["Each item of the list is a tuple of two values, so the loop needs two variables.","Write the two variable names, separated by a comma: `name, score`."],"tests":[{"name":"Output","stdin":"","expect":"Ada: 92 points\nMax: 78 points\nLin: 85 points","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Write a function `share(amount, people)` that shares `amount` sweets equally between `people` people. It returns two values: how many whole sweets each person gets, and how many are left over.\n\nFor example, `share(17, 5)` returns `(3, 2)`: everyone gets 3, and 2 are left.\n","kind":"code","seed":"def share(amount: int, people: int) -> tuple:\n    pass\n\n\nif __name__ == \"__main__\":\n    each, left = share(17, 5)\n    print(each, left)\n","solution":"def share(amount: int, people: int) -> tuple:\n    return amount // people, amount % people\n\n\nif __name__ == \"__main__\":\n    each, left = share(17, 5)\n    print(each, left)\n","hints":["`//` gives the whole part of a division, and `%` gives what's left over.","Return both, separated by a comma: `return amount // people, amount % people`."],"tests":[{"name":"share(17, 5)","stdin":"","call":"share(17, 5)\n","expect":"(3, 2)","hidden":false,"returns":true},{"name":"share(20, 4)","stdin":"","call":"share(20, 4)\n","expect":"(5, 0)","hidden":true,"returns":true},{"name":"share(3, 7)","stdin":"","call":"share(3, 7)\n","expect":"(0, 3)","hidden":true,"returns":true}],"require":[],"forbid":[]},{"task":"Write a function `best_and_worst(results)` that takes a list of `(name, score)` tuples and returns two values: the name with the highest score and the name with the lowest score. No two scores are the same.\n\nFor example, `best_and_worst([(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)])` returns `('Ada', 'Max')`.\n","kind":"code","seed":"def best_and_worst(results: list) -> tuple:\n    pass\n\n\nif __name__ == \"__main__\":\n    best, worst = best_and_worst([(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)])\n    print(best, worst)\n","solution":"def best_and_worst(results: list) -> tuple:\n    best_name, best_score = results[0]\n    worst_name, worst_score = results[0]\n    for name, score in results:\n        if score > best_score:\n            best_name, best_score = name, score\n        if score < worst_score:\n            worst_name, worst_score = name, score\n    return best_name, worst_name\n\n\nif __name__ == \"__main__\":\n    best, worst = best_and_worst([(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)])\n    print(best, worst)\n","hints":["Start with the first tuple as both the best and the worst so far. Unpacking gives its name and score in one line.","Go through the tuples with `for name, score in results:` and update the best when a score is higher, and the worst when it's lower.","Return both names, separated by a comma: `return best_name, worst_name`."],"tests":[{"name":"best_and_worst([(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)])","stdin":"","call":"best_and_worst([(\"Ada\", 92), (\"Max\", 78), (\"Lin\", 85)])\n","expect":"('Ada', 'Max')","hidden":false,"returns":true},{"name":"best_and_worst([(\"Kim\", 40), (\"Bo\", 75)])","stdin":"","call":"best_and_worst([(\"Kim\", 40), (\"Bo\", 75)])\n","expect":"('Bo', 'Kim')","hidden":true,"returns":true},{"name":"best_and_worst([(\"Cy\", 10), (\"Di\", 30), (\"Ed\", 20), (\"Fa\", 5)])","stdin":"","call":"best_and_worst([(\"Cy\", 10), (\"Di\", 30), (\"Ed\", 20), (\"Fa\", 5)])\n","expect":"('Di', 'Fa')","hidden":true,"returns":true},{"name":"best_and_worst([(\"Solo\", 50)])","stdin":"","call":"best_and_worst([(\"Solo\", 50)])\n","expect":"('Solo', 'Solo')","hidden":true,"returns":true}],"require":[],"forbid":[]}]}