Question presented to candidate:
"You see def handler(*args, **kwargs) all over a codebase. What do the single and double star actually do, what types do args and kwargs end up as, and how is that different from putting a star in front of something when you call a function?"
What a strong answer should cover:
- In a definition,
*argscollects any extra positional arguments into a tuple and**kwargscollects any extra keyword arguments into a dict; the names are convention, the stars are the syntax - At a call site the stars do the reverse:
f(*seq)spreads an iterable into positional arguments andf(**mapping)spreads a mapping into keyword arguments (string keys only) - Parameter order: regular parameters, then
*args, then keyword-only parameters, then**kwargs; anything after*argscan only be passed by keyword - The forwarding pattern
def wrapper(*args, **kwargs): return func(*args, **kwargs)used by decorators, and the cost: a vaguer signature for callers and type checkers - Details: each call gets a fresh tuple and dict,
kwargskeeps the caller order (guaranteed since Python 3.6, PEP 468), and filling the same parameter twice raisesTypeError
Code / implementation expected: Optional β a few lines showing packing in a def and unpacking in a call, ideally a small forwarding wrapper.