PART 3 · ADVANCED PYTHON · PRACTICE
Practice set 2: advanced
FreeLesson 38 of 78
Generators, itertools, decorators and classes, the way coding rounds ask for them.
Q12Write chunked(iterable, n) that yields lists of n items, without itertools.batched. It must work on a generator.
DE MEDIUM
Approach: islice pulls n items from one shared iterator until a slice comes back empty.
from itertools import islice
def chunked(iterable, n):
it = iter(iterable) # one shared iterator
while batch := list(islice(it, n)):
yield batch
print(list(chunked(range(101, 108), 3)))
print(list(chunked((x for x in "abcde"), 2)))Output
[[101, 102, 103], [104, 105, 106], [107]] [['a', 'b'], ['c', 'd'], ['e']]
Q13Run-length encode a status stream: ["D","D","C","D","D","D"] becomes "D2C1D3".DEEASY
Approach: groupby on unsorted input is exactly right here: we want runs of neighbours.
from itertools import groupby
stream = ["D", "D", "C", "D", "D", "D"]
runs = (f"{k}{sum(1 for _ in g)}" for k, g in groupby(stream))
print("".join(runs))Output
D2C1D3
Q14Write a decorator count_calls that records how many times each decorated function ran.DEMEDIUM
Approach: Store state on the wrapper itself, and keep the name with functools.wraps.
import functools
def count_calls(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
wrapper.calls += 1
return fn(*args, **kwargs)
wrapper.calls = 0
return wrapper
@count_calls
def load(batch): return len(batch)
for b in ([1, 2], [3], [4, 5, 6]):
load(b)
print(load.__name__, load.calls)Output
load 3
Q15Sort employees.csv by department A to Z, then salary high to low, then name. Print the top two per
department. DE MEDIUM
Approach: One sort with a tuple key (salary negated), then groupby on the now-sorted department.
import csv
from itertools import groupby, islice
rows = list(csv.DictReader(open("employees.csv")))
rows.sort(key=lambda r: (r["dept"], -int(r["salary"]), r["name"]))
for dept, group in groupby(rows, key=lambda r: r["dept"]):
top = [(r["name"], r["salary"]) for r in islice(group, 2)]
print(dept, top)Output
Analytics [('Ishita', '160000'), ('Neha', '150000')]
Engineering [('Anita', '250000'), ('Rahul', '180000')]
Sales [('Dev', '90000'), ('Tara', '90000')]Practice before you move on
- Solve Q12 to Q15 in the Try it editor before you read each solution.
- Use chunked() from Q12 on a generator of rows from orders.csv and print each chunk's order_ids.