Mastery
Mastery/Python/C. Functions & closures
T1 · high-leverage

Positional-only (/) and keyword-only (*) parameters

def f(a, b, /, c, d, *, e, f): everything before / MUST be passed positionally; everything after * MUST be passed by keyword; c, d in the middle can be either. This is how stdlib functions like len() lock down their signature (you can't call len(obj=x)), and it's increasingly used in library code to keep parameter names as an implementation detail that can change without breaking callers.

python
def f(a, b, /, c, d, *, e, f):
    return (a, b, c, d, e, f)

print(f(1, 2, 3, d=4, e=5, f=6))
print(f(1, 2, c=3, d=4, e=5, f=6))

try:
    f(a=1, b=2, c=3, d=4, e=5, f=6)   # a, b are positional-only
except TypeError as ex:
    print("TypeError:", ex)

try:
    f(1, 2, 3, 4, 5, 6)   # e, f are keyword-only
except TypeError as ex:
    print("TypeError:", ex)

Interview angle

Less a "gotcha" and more a "how current is your Python" signal — a candidate who knows / and * syntax and can explain why an API designer would reach for them (freedom to rename parameters internally without breaking callers who pass positionally) shows they think about API design deliberately, not just consume APIs other people designed.

In the industry

The standard library itself uses positional-only parameters post-3.8 specifically to keep implementation details out of the public contract (dict.get's signature is a common example). API-design-conscious teams adopt the same convention for their own public functions for the same reason: parameter names become a free-to-change internal detail instead of an accidental part of the API surface that breaking-change policies have to account for.