Python ships with a large standard library — the “batteries included” its users have bragged about for thirty years. Knowing what is in the box saves you from writing it again.
Four ways to import
import math # the whole module
print(math.sqrt(16), math.pi)
from math import sqrt, pi # specific names
print(sqrt(25), pi)
import statistics as stats # with a shorter alias
print(stats.mean([1, 2, 3, 4]))
from math import * # everything - do not do this
print(cos(0))Prefer the first two. import math keeps the origin of math.sqrt visible;
from math import * dumps unknown names into your namespace and quietly
shadows your own.
math and random
import math
import random
print(math.sqrt(144), math.floor(3.7), math.ceil(3.2))
print(math.factorial(5), round(math.log(100, 10)))
random.seed(7) # same seed, same sequence - handy for tests
print(random.randint(1, 6))
print(random.random())
print(random.choice(["rock", "paper", "scissors"]))
deck = list(range(1, 11))
random.shuffle(deck)
print(deck)
print(random.sample(deck, 3))datetime
from datetime import date, datetime, timedelta
today = date(2026, 1, 9)
print(today, today.year, today.strftime("%A, %d %B %Y"))
launch = date(2026, 3, 1)
gap = launch - today
print(f"{gap.days} days until launch")
print(today + timedelta(days=90))
parsed = datetime.strptime("2026-01-09 14:30", "%Y-%m-%d %H:%M")
print(parsed, parsed.hour)strftime formats a date into text; strptime parses text into a date. The
codes are the same both ways: %Y four-digit year, %m month, %d day, %H
hour, %M minute, %A weekday name, %B month name.
json
JSON is how programs exchange structured data. The mapping to Python is almost one to one: objects become dictionaries, arrays become lists.
import json
data = {
"name": "Ada",
"languages": ["Python", "Analytical Engine"],
"active": True,
"score": None,
}
text = json.dumps(data, indent=2) # Python -> JSON text
print(text)
restored = json.loads(text) # JSON text -> Python
print(type(restored), restored["languages"][0])
print(restored["active"] is True, restored["score"] is None)Note the translation: Python’s True becomes true, None becomes null.
json.dump() and json.load() (no “s”) do the same to and from a file object.
collections
Three tools here save real work.
from collections import Counter, defaultdict, namedtuple
words = "the quick brown fox the lazy dog the end".split()
counts = Counter(words)
print(counts.most_common(2))
print(counts["the"], counts["missing"]) # missing keys are 0, not an error
groups = defaultdict(list) # a missing key auto-creates []
for word in words:
groups[len(word)].append(word)
print(dict(groups))
Point = namedtuple("Point", ["x", "y"]) # a tuple with named fields
p = Point(3, 4)
print(p, p.x, p.y)Counter is the word-count exercise from Day 3 in a single call.
pathlib
The modern way to handle paths — no string concatenation, no separators to get wrong.
from pathlib import Path
folder = Path("data")
folder.mkdir(exist_ok=True)
note = folder / "note.txt" # / joins paths on any OS
note.write_text("Written through pathlib\n")
print(note)
print(note.name, note.suffix, note.stem)
print(note.exists())
print(note.read_text())
for item in folder.iterdir():
print(" found:", item)Writing your own module
Any .py file is a module. The next playground holds two files — click the
tabs above the editor to switch between them.
Imports look in the same folder first, so from geometry import ... finds
geometry.py sitting next to main.py. That is all a module is.
if __name__ == '__main__'
Code at the top level of a module runs on import. Guarding it with
if __name__ == "__main__": means it runs only when the file is executed
directly — so a module can be both an importable library and a runnable script.
Before you write your own
Predict. Four modules’ worth of lines. The date one crosses a month.
from collections import Counter
from datetime import date, timedelta
import json
meals = Counter(["pasta", "rice", "pasta", "soup", "pasta"])
print(meals.most_common(1))
print(meals["pizza"])
start = date(2026, 1, 30)
print(start + timedelta(days=3))
print(json.dumps({"done": True, "note": None}))Check your prediction
[('pasta', 3)]
0
2026-02-02
{"done": true, "note": null}A Counter answers 0 for something it never saw, rather than raising.
timedelta handles month ends for you. And JSON spells Python’s True and
None as true and null.
Fix. A to-do list saved as JSON should come back as a list you can loop over. Instead this prints one character per line.
import json
tasks = ["buy milk", "call Sam"]
text = json.dumps(tasks)
for task in text:
print(task)Check your fix
import json
tasks = ["buy milk", "call Sam"]
text = json.dumps(tasks)
for task in json.loads(text):
print(task)buy milk
call Samjson.dumps returns a string — that’s what makes it saveable — and looping
over a string gives you its characters. json.loads turns the text back into a
list.
A dice-rolling report
Roll two six-sided dice 1,000 times and report how often each total from 2 to 12 came up, as a percentage to one decimal place. Seed the generator with 42 so your run is reproducible.
You should get eleven lines, one for each total from 2 to 12, with 7 the most
common — in the long run it comes up one time in six, so expect roughly 15 to
18%. Your exact percentages depend on the order you call random in, so they
may not match the solution’s to the digit.
import random
from collections import Counter
random.seed(42)
# Your code hereHint 1: the idea
Two parts: simulate, then report. One roll of two dice is
random.randint(1, 6) + random.randint(1, 6). Doing that 1,000 times and
counting how often each total appears is exactly what Counter is for. The
report is then a loop over the totals 2 to 12.
Hint 2: a first step
Make one roll and print it. Then collect 1,000 of them in a list, and pass the
list to Counter — print that, and you’ll see every total with its count. A
count out of 1,000 becomes a percentage when you divide by 10.
Show one solution
import random
from collections import Counter
random.seed(42)
rolls = Counter(
random.randint(1, 6) + random.randint(1, 6)
for _ in range(1000)
)
for total in range(2, 13):
count = rolls[total]
bar = "#" * (count // 10)
print(f"{total:2}: {count / 10:5.1f}% {bar}")A generator expression feeding Counter does the whole simulation in one
statement, and rolls[total] returns 0 for any total that never came up.
What you learned
import moduleandfrom module import nameare the imports to use.math,random,datetime,json,collectionsandpathlibcover an enormous amount of everyday work.- JSON maps onto Python dictionaries and lists almost exactly.
Countercounts,defaultdictremoves missing-key checks,namedtuplenames tuple fields.- Any
.pyfile next to yours is importable as a module.