{"id":"modules-contents","slug":"contents","title":"What a module contains","text":"How do you find out what's in a module? There are two ways: read its documentation, or ask Python itself.\n\n### The documentation\n\nEvery module of the standard library has a page in Python's official documentation. The list of all of them, grouped by theme, is at [docs.python.org/3/library](https://docs.python.org/3/library/), and the `math` module's page is [docs.python.org/3/library/math.html](https://docs.python.org/3/library/math.html). Each function has a short description, and often an example. Looking things up there is part of every programmer's day, so it's worth getting used to it early.\n\n### dir\n\nIn part 4 you used `dir(\"\")` to list the methods of strings. Given a module, `dir` lists the names the module contains. The list for `math` is long, so this session looks at its end, and checks for one name:\n\n```pycon\n>>> import math\n>>> names = dir(math)\n>>> names[-7:]\n['sqrt', 'sumprod', 'tan', 'tanh', 'tau', 'trunc', 'ulp']\n>>> \"floor\" in names\nTrue\n```\n\nThe list is in alphabetical order. It starts with names wrapped in double underscores, such as `__name__`, which Python uses for its own bookkeeping; you can skip those. `dir` shows only the names, so it's a quick reminder of how something was spelled. The documentation tells what each one does.\n\n### Modules hold values too\n\nNot everything in a module is a function. The `string` module holds handy strings of characters:\n\n```python\nimport string\n\nprint(string.ascii_lowercase)\nprint(string.ascii_uppercase)\nprint(string.digits)\nprint(string.punctuation)\n```\n\n```output\nabcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789\n!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n```\n\n(`string.ascii_letters` has both the small and the capital letters.) These save typing, and typos: a hand-typed alphabet with one letter missing is a bug that hides well. Together with `in` they make it easy to sort characters into groups:\n\n```python\nimport string\n\ncode = \"AB-12\"\ndigits = 0\nfor character in code:\n    if character in string.digits:\n        digits += 1\nprint(\"Digits:\", digits)\n```\n\n```output\nDigits: 2\n```\n\nNote the difference between the module `string` and the type of text values, `str`: they're two different things with similar names.\n","task":"What does this program print? Type each line it prints.\n","kind":"predict","seed":"import string\n\nprint(len(string.digits))\nprint(\"7\" in string.digits)\nprint(string.ascii_uppercase[:5])\nprint(\"a\" in string.ascii_uppercase)\n","solution":"import string\n\nprint(len(string.digits))\nprint(\"7\" in string.digits)\nprint(string.ascii_uppercase[:5])\nprint(\"a\" in string.ascii_uppercase)\n","hints":["`string.digits` is the string `0123456789`.","`string.ascii_uppercase` holds the capital letters A to Z, and `[:5]` takes its first five characters.","Small and capital letters are different characters."],"tests":[{"name":"Output","stdin":"","expect":"10\nTrue\nABCDE\nFalse","hidden":false}],"require":[],"forbid":[],"lines":["10","True","ABCDE","False"],"more":[{"task":"A website accepts a username only if it is 3 to 12 characters long and has nothing but small letters a to z, digits and underscores (`_`). Write a function `valid_username(name)` that returns `True` for a valid username and `False` otherwise. Use the strings of the `string` module instead of typing the letters and digits yourself.\n\n`valid_username(\"ada_99\")` returns `True`, and `valid_username(\"Ada\")` returns `False`.\n","kind":"code","seed":"import string\n\n\ndef valid_username(name):\n    pass\n\n\nif __name__ == \"__main__\":\n    print(valid_username(\"ada_99\"))\n    print(valid_username(\"Ada\"))\n","solution":"import string\n\n\ndef valid_username(name):\n    if len(name) < 3 or len(name) > 12:\n        return False\n    allowed = string.ascii_lowercase + string.digits + \"_\"\n    for character in name:\n        if character not in allowed:\n            return False\n    return True\n\n\nif __name__ == \"__main__\":\n    print(valid_username(\"ada_99\"))\n    print(valid_username(\"Ada\"))\n","hints":["Check the length first, and return `False` right away if it's wrong.","Make one string of all the allowed characters: `string.ascii_lowercase + string.digits + \"_\"`.","Loop over the characters of the name. As soon as one is `not in` the allowed string, return `False`. If the loop finishes, the name is valid."],"tests":[{"name":"valid_username(\"ada_99\")","stdin":"","call":"valid_username(\"ada_99\")\n","expect":"True","hidden":false,"returns":true},{"name":"valid_username(\"Ada\")","stdin":"","call":"valid_username(\"Ada\")\n","expect":"False","hidden":false,"returns":true},{"name":"valid_username(\"a b\")","stdin":"","call":"valid_username(\"a b\")\n","expect":"False","hidden":true,"returns":true},{"name":"valid_username(\"x1\")","stdin":"","call":"valid_username(\"x1\")\n","expect":"False","hidden":true,"returns":true},{"name":"valid_username(\"python_arena_fan\")","stdin":"","call":"valid_username(\"python_arena_fan\")\n","expect":"False","hidden":true,"returns":true},{"name":"valid_username(\"snake_case\")","stdin":"","call":"valid_username(\"snake_case\")\n","expect":"True","hidden":true,"returns":true},{"name":"valid_username(\"abc!\")","stdin":"","call":"valid_username(\"abc!\")\n","expect":"False","hidden":true,"returns":true},{"name":"valid_username(\"abcdefghijkl\")","stdin":"","call":"valid_username(\"abcdefghijkl\")\n","expect":"True","hidden":true,"returns":true}],"require":[{"pattern":"\\bascii_lowercase\\b","message":"Use `string.ascii_lowercase` for the letters a to z instead of typing them."},{"pattern":"\\bdigits\\b","message":"Use `string.digits` for the digits instead of typing them."}],"forbid":[]},{"task":"Reading the documentation of `math` turns up `math.comb(n, k)`: the number of different ways to choose `k` things out of `n`, when the order doesn't matter. A chess club with 12 members that sends 4 players to a tournament can pick its team in `math.comb(12, 4)` different ways. (Ada, Ben, Cy and Di are the same team as Di, Cy, Ben and Ada.)\n\nWrite a program that asks how many members the club has and how many players go to the tournament, and prints how many different teams there are. For example:\n\n```\nMembers in the club: 12\nPlayers in a team: 4\nDifferent teams: 495\n```\n","kind":"code","seed":"import math\n\n# Write your program here.\n","solution":"import math\n\nmembers = int(input(\"Members in the club: \"))\nplayers = int(input(\"Players in a team: \"))\nprint(\"Different teams:\", math.comb(members, players))\n","hints":["Read the two numbers with `int(input(...))`, using the prompts of the example.","The number of different teams is `math.comb(members, players)`: the number to choose from first, then how many are chosen."],"tests":[{"name":"Test 1","stdin":"12\n4\n","expect":"Members in the club: 12\nPlayers in a team: 4\nDifferent teams: 495","hidden":false},{"name":"Test 2","stdin":"52\n5\n","expect":"Members in the club: 52\nPlayers in a team: 5\nDifferent teams: 2598960","hidden":true},{"name":"Test 3","stdin":"10\n2\n","expect":"Members in the club: 10\nPlayers in a team: 2\nDifferent teams: 45","hidden":true},{"name":"Test 4","stdin":"6\n6\n","expect":"Members in the club: 6\nPlayers in a team: 6\nDifferent teams: 1","hidden":true}],"require":[{"pattern":"math\\.comb\\s*\\(","message":"Calculate the number of teams with `math.comb`."}],"forbid":[]}]}