{"id":"lists-in-functions","slug":"lists-and-functions","title":"Lists as arguments and return values","text":"Your own functions can take a list as an argument, just like `len` and `max` do. The type hint for a list is `list`:\n\n```python\ndef summary(numbers: list) -> str:\n    return f\"{len(numbers)} numbers from {min(numbers)} to {max(numbers)}\"\n\n\nprint(summary([4, 18, 9]))\nages = [34, 7, 61, 25, 12]\nprint(summary(ages))\n```\n\n```output\n3 numbers from 4 to 18\n5 numbers from 7 to 61\n```\n\nInside the function, the parameter `numbers` is the list that was given in the call: first `[4, 18, 9]`, then the list in `ages`.\n\nA function can also return a list. This one reads words until an empty line and returns them all:\n\n```python\ndef read_words(prompt: str) -> list:\n    words = []\n    while True:\n        word = input(prompt)\n        if word == \"\":\n            break\n        words.append(word)\n    return words\n\n\nfruit = read_words(\"Fruit: \")\nprint(\"In order:\", sorted(fruit))\nprint(\"Alphabetically last:\", max(fruit))\n```\n\n```input\nplum\nbanana\nfig\n\n```\n\n```output\nFruit: plum\nFruit: banana\nFruit: fig\nFruit:\nIn order: ['banana', 'fig', 'plum']\nAlphabetically last: plum\n```\n\nThe function builds the list in a variable of its own and returns it when the loop ends. The code that called it stores the list and goes on working with it.\n\n### What functions buy you\n\nRead the last three lines of that program: read the fruit, print them in order, print the last one. Each line says *what* happens, while *how* it happens (the loop, the empty line, `append`) is tucked away in `read_words`. A program split into named pieces is easier to follow, and when something goes wrong, the name tells you where to look.\n\nA function also does its job wherever it's needed. Here `spread` is written once and used by two other functions:\n\n```python\ndef spread(numbers: list) -> int:\n    return max(numbers) - min(numbers)\n\n\ndef weather(temperatures: list) -> str:\n    if spread(temperatures) > 10:\n        return \"a day of big changes\"\n    return \"a steady day\"\n\n\ndef judges(scores: list) -> str:\n    return f\"the judges differ by up to {spread(scores)} points\"\n\n\nprint(weather([12, 19, 25, 14]))\nprint(weather([20, 22, 21]))\nprint(judges([7, 9, 8, 6]))\n```\n\n```output\na day of big changes\na steady day\nthe judges differ by up to 3 points\n```\n\nIf `spread` had a bug, you would fix it in one place, and both functions would be right again.\n","task":"Write the function `price_range(prices: list) -> str`, which returns the lowest and the highest price of a list as text. For example, `price_range([12, 3, 8])` returns `'from 3 to 12'`.\n","kind":"code","seed":"def price_range(prices: list) -> str:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(price_range([12, 3, 8]))\n","solution":"def price_range(prices: list) -> str:\n    return f\"from {min(prices)} to {max(prices)}\"\n\n\nif __name__ == \"__main__\":\n    print(price_range([12, 3, 8]))\n","hints":["`min(prices)` and `max(prices)` give the lowest and the highest price.","Return an f-string that has `min(prices)` and `max(prices)` in its braces, with the words `from` and `to` around them."],"tests":[{"name":"price_range([12, 3, 8])","stdin":"","call":"price_range([12, 3, 8])\n","expect":"'from 3 to 12'","hidden":false,"returns":true},{"name":"price_range([5])","stdin":"","call":"price_range([5])\n","expect":"'from 5 to 5'","hidden":true,"returns":true},{"name":"price_range([20, 45, 7, 99, 30])","stdin":"","call":"price_range([20, 45, 7, 99, 30])\n","expect":"'from 7 to 99'","hidden":true,"returns":true}],"require":[],"forbid":[],"more":[{"task":"In some sports, a performance gets scores from several judges, and the highest and the lowest score are left out so that one strict or generous judge can't decide the result. Write the function `fair_average(scores: list) -> float`, which returns the average of the scores without the single highest and the single lowest score. The list has at least three scores. For example, `fair_average([7, 9, 8, 2])` leaves out 9 and 2, and returns `7.5`.\n","kind":"code","seed":"def fair_average(scores: list) -> float:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(fair_average([7, 9, 8, 2]))\n","solution":"def fair_average(scores: list) -> float:\n    total = sum(scores) - max(scores) - min(scores)\n    return total / (len(scores) - 2)\n\n\nif __name__ == \"__main__\":\n    print(fair_average([7, 9, 8, 2]))\n","hints":["Leaving out the highest and the lowest score means subtracting `max(scores)` and `min(scores)` from `sum(scores)`.","Two scores are left out, so divide by `len(scores) - 2`.","Don't remove the items from the list itself: the list belongs to the code that called the function, so work with `sum`, `max` and `min` instead."],"tests":[{"name":"fair_average([7, 9, 8, 2])","stdin":"","call":"fair_average([7, 9, 8, 2])\n","expect":"7.5","hidden":false,"returns":true},{"name":"fair_average([5, 5, 5])","stdin":"","call":"fair_average([5, 5, 5])\n","expect":"5.0","hidden":true,"returns":true},{"name":"fair_average([10, 1, 6, 8, 3])","stdin":"","call":"fair_average([10, 1, 6, 8, 3])\n","expect":"5.666666666666667","hidden":true,"returns":true}],"require":[],"forbid":[{"pattern":"\\.(remove|pop)\\s*\\(","message":"Leave the list as it is: the code that called the function may still need it. Calculate with `sum`, `max` and `min`."}]},{"task":"Write the function `numbers_between(start: int, end: int) -> list`, which returns a new list of the whole numbers from `start` to `end`, both included. If `start` is greater than `end`, the list is empty. For example, `numbers_between(3, 6)` returns `[3, 4, 5, 6]`.\n","kind":"code","seed":"def numbers_between(start: int, end: int) -> list:\n    pass\n\n\nif __name__ == \"__main__\":\n    print(numbers_between(3, 6))\n","solution":"def numbers_between(start: int, end: int) -> list:\n    numbers = []\n    number = start\n    while number <= end:\n        numbers.append(number)\n        number += 1\n    return numbers\n\n\nif __name__ == \"__main__\":\n    print(numbers_between(3, 6))\n","hints":["Start with an empty list, `numbers = []`, and a counter that starts from `start`.","In a `while` loop that runs as long as the counter is at most `end`, append the counter and add 1 to it.","After the loop, `return numbers`. When `start` is greater than `end`, the loop never runs and the empty list is returned."],"tests":[{"name":"numbers_between(3, 6)","stdin":"","call":"numbers_between(3, 6)\n","expect":"[3, 4, 5, 6]","hidden":false,"returns":true},{"name":"numbers_between(-2, 2)","stdin":"","call":"numbers_between(-2, 2)\n","expect":"[-2, -1, 0, 1, 2]","hidden":true,"returns":true},{"name":"numbers_between(5, 5)","stdin":"","call":"numbers_between(5, 5)\n","expect":"[5]","hidden":true,"returns":true},{"name":"numbers_between(7, 4)","stdin":"","call":"numbers_between(7, 4)\n","expect":"[]","hidden":true,"returns":true}],"require":[],"forbid":[]}]}