Python course menu
Python Function Parameters: Defaults, *args, **kwargs and Type Hints
Learn every kind of Python function parameter: required parameters, default values, the mutable default trap, *args for any number of values, **kwargs for named options, keyword-only parameters, and type hints.
On this page
Parameters are the names listed in a function's definition. They decide what information a function needs and how callers can pass it. (The values passed in when calling are arguments, covered in the next lesson.)
Required parameters#
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet("Asha", "Hello")Hello, Asha!Every parameter without a default must receive a value:
greet("Asha")TypeError: greet() missing 1 required positional argument: 'greeting'Default values#
Give a parameter a default with =. Callers can then leave it out:
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")
greet("Asha")
greet("Ravi", "Welcome")Hello, Asha!
Welcome, Ravi!Parameters with defaults must come after those without. Defaults make functions flexible: callers specify only what differs from the usual case.
def make_order(item, qty=1, gift_wrap=False):
wrap = " (gift wrapped)" if gift_wrap else ""
return f"{qty} x {item}{wrap}"
print(make_order("Notebook"))
print(make_order("Pen", 10))
print(make_order("Book", gift_wrap=True))1 x Notebook
10 x Pen
1 x Book (gift wrapped)The mutable default trap#
Default values are created once, when the function is defined, not each time it is called. With a list as a default, every call shares the same list:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("a"))
print(add_item("b"))['a']
['a', 'b']The second call "remembered" the first. The fix is to use None and create the list inside:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item("a"))
print(add_item("b"))['a']
['b']*args: any number of positional values#
A parameter starting with * collects all extra positional arguments into a tuple:
def total(*numbers):
print(numbers)
return sum(numbers)
print(total(1, 2, 3))
print(total())(1, 2, 3)
6
()
0print() itself works this way, which is why it accepts any number of values.
**kwargs: any number of named values#
A parameter starting with ** collects extra keyword arguments into a dictionary:
def profile(name, **details):
print(name, details)
profile("Asha", age=21, city="Pune")Asha {'age': 21, 'city': 'Pune'}The names args and kwargs are only conventions; the * and ** do the work.
Keyword-only parameters#
Parameters after a bare * must be passed by name. That makes calls self-explanatory and prevents mix-ups:
def describe(name, *, city):
return f"{name} from {city}"
print(describe("Asha", city="Pune"))
print(describe("Asha", "Pune"))Asha from Pune
TypeError: describe() takes 1 positional argument but 2 were givenThe full order#
When combining them, parameters must appear in this order:
def f(required, optional="x", *args, keyword_only, **kwargs):
...Type hints#
You can annotate parameters and the return value with types. Python does not enforce them at runtime, but editors and tools like mypy use them to catch mistakes:
def area(width: float, height: float = 1.0) -> float:
return width * height
print(area(3, 4.5), area(2))13.5 2.0Common mistakes#
Practice#
Practice exercise
Write price_with_tax(price, rate=0.18, round_to=2) that returns the price including tax, rounded to round_to decimal places. Call it three ways: only a price; a price and a 5% rate; and a price of 99.99 rounded to 0 decimal places using a keyword argument.
Show hint
round(price * (1 + rate), round_to).
Show solution
def price_with_tax(price, rate=0.18, round_to=2):
return round(price * (1 + rate), round_to)
print(price_with_tax(100))
print(price_with_tax(100, 0.05))
print(price_with_tax(99.99, round_to=0))118.0
105.0
118.0The keyword round_to=0 lets you skip rate and keep its default.
Key takeaway#
Finished this lesson?