A function with three parameters:
def make_person(name, age, city):
return {"name": name, "age": age, "city": city}
make_person("Ada", 36, "London") # positionalReading the call site, I can't tell which is name vs city without looking at the def.
Exactly the problem keyword arguments solve. Pass name=value in the call:
make_person(name="Ada", age=36, city="London")Now the call is self-documenting. And kwargs can come in any order:
make_person(city="London", name="Ada", age=36) # same resultCan I mix positional and keyword?
Yes — positionals first, kwargs after:
make_person("Ada", age=36, city="London") # OK
make_person(name="Ada", 36, "London") # SyntaxError — positional after kwargA common shape: leave the first 1-2 args positional (obvious from context) and use kwargs for the rest:
open("data.txt", mode="w", encoding="utf-8")
requests.get("https://...", headers={"X": "y"}, timeout=5)When should I always use kwargs?
Two heuristics. (1) When the function has 3+ parameters — positional-only call sites become illegible. (2) When booleans or short strings are involved — f(True, False, "r") tells you nothing; f(strict=True, eager=False, mode="r") tells you everything.
name=value at the call sitedef make_person(name, age, city):
return {"name": name, "age": age, "city": city}
# all three styles produce the same result:
make_person("Ada", 36, "London")
make_person(name="Ada", age=36, city="London")
make_person("Ada", city="London", age=36)f(1, x=2) is OK; f(x=2, 1) is a SyntaxError.f(1, name="Ada") works only if name isn't also the first positional. f("Ada", name="Bob") is a TypeError: multiple values for argument 'name'.Readability at the call site:
# Positional — what is each True?
do_thing(True, False, True, False, 100)
# Keyword — every value tells you what it does
do_thing(strict=True, dry_run=False, eager=True, retry=False, timeout=100)Most stdlib functions accept keywords for clarity:
open("data.txt", mode="r", encoding="utf-8")
sorted(items, key=len, reverse=True)
print("hello", "world", sep=", ", end="!\n")Keyword args become especially useful when combined with defaults:
def connect(host, port=5432, timeout=30, retries=3):
...
connect("db.local") # all defaults
connect("db.local", retries=5) # override only retries
connect("db.local", timeout=60, retries=5) # any combination, order-freeThe caller doesn't have to remember the order of port, timeout, retries — they name the one they want to override.
A * in the parameter list forces every following parameter to be keyword-only:
def f(a, b, *, strict=False): # strict can ONLY be passed by keyword
...
f(1, 2, strict=True) # OK
f(1, 2, True) # TypeError — too many positional argsUseful to lock down booleans and confusing flags. Lesson 11 shows this in the context of *args.
A function with three parameters:
def make_person(name, age, city):
return {"name": name, "age": age, "city": city}
make_person("Ada", 36, "London") # positionalReading the call site, I can't tell which is name vs city without looking at the def.
Exactly the problem keyword arguments solve. Pass name=value in the call:
make_person(name="Ada", age=36, city="London")Now the call is self-documenting. And kwargs can come in any order:
make_person(city="London", name="Ada", age=36) # same resultCan I mix positional and keyword?
Yes — positionals first, kwargs after:
make_person("Ada", age=36, city="London") # OK
make_person(name="Ada", 36, "London") # SyntaxError — positional after kwargA common shape: leave the first 1-2 args positional (obvious from context) and use kwargs for the rest:
open("data.txt", mode="w", encoding="utf-8")
requests.get("https://...", headers={"X": "y"}, timeout=5)When should I always use kwargs?
Two heuristics. (1) When the function has 3+ parameters — positional-only call sites become illegible. (2) When booleans or short strings are involved — f(True, False, "r") tells you nothing; f(strict=True, eager=False, mode="r") tells you everything.
name=value at the call sitedef make_person(name, age, city):
return {"name": name, "age": age, "city": city}
# all three styles produce the same result:
make_person("Ada", 36, "London")
make_person(name="Ada", age=36, city="London")
make_person("Ada", city="London", age=36)f(1, x=2) is OK; f(x=2, 1) is a SyntaxError.f(1, name="Ada") works only if name isn't also the first positional. f("Ada", name="Bob") is a TypeError: multiple values for argument 'name'.Readability at the call site:
# Positional — what is each True?
do_thing(True, False, True, False, 100)
# Keyword — every value tells you what it does
do_thing(strict=True, dry_run=False, eager=True, retry=False, timeout=100)Most stdlib functions accept keywords for clarity:
open("data.txt", mode="r", encoding="utf-8")
sorted(items, key=len, reverse=True)
print("hello", "world", sep=", ", end="!\n")Keyword args become especially useful when combined with defaults:
def connect(host, port=5432, timeout=30, retries=3):
...
connect("db.local") # all defaults
connect("db.local", retries=5) # override only retries
connect("db.local", timeout=60, retries=5) # any combination, order-freeThe caller doesn't have to remember the order of port, timeout, retries — they name the one they want to override.
A * in the parameter list forces every following parameter to be keyword-only:
def f(a, b, *, strict=False): # strict can ONLY be passed by keyword
...
f(1, 2, strict=True) # OK
f(1, 2, True) # TypeError — too many positional argsUseful to lock down booleans and confusing flags. Lesson 11 shows this in the context of *args.
Create a free account to get started. Paid plans unlock all tracks.