indusai.co

Arguments

Python gives you a lot of flexibility in how arguments are passed to functions. Understanding the options makes library documentation much easier to read.

Positional arguments

Matched to parameters by position.

python
def describe(name, age):
    print(f"{name} is {age}")

describe("Ravi", 30)

The number of arguments must match, or Python raises TypeError.

Keyword arguments

Matched by name, so order does not matter and the call documents itself.

python
def describe(name, age):
    print(f"{name} is {age}")

describe(age=30, name="Ravi")

Positional arguments must come before keyword arguments in a call.

Default values

A parameter with a default is optional.

python
def power(base, exponent=2):
    return base ** exponent

print(power(5))
print(power(5, 3))
print(power(exponent=4, base=2))

Parameters with defaults must come after those without.

python
def add(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add(1))
print(add(2))

*args: any number of positional arguments

The extra arguments arrive as a tuple.

python
def total(*numbers):
    print(numbers)
    return sum(numbers)

print(total(1, 2, 3))
print(total())

**kwargs: any number of keyword arguments

They arrive as a dictionary.

python
def show(**details):
    for key, value in details.items():
        print(f"{key} = {value}")

show(name="Ira", city="Goa", age=25)

Combining them

The order in a definition is always: positional, *args, keyword only, **kwargs.

python
def report(title, *values, unit="", **meta):
    print(title, values, unit, meta)

report("Temps", 31, 33, 29, unit="C", city="Jaipur")

Unpacking arguments in a call

* spreads a list into positional arguments; ** spreads a dictionary into keyword arguments.

python
def area(w, h):
    return w * h

size = [4, 5]
print(area(*size))

opts = {"w": 2, "h": 3}
print(area(**opts))

Keyword only and positional only

A bare * in the definition forces everything after it to be passed by keyword. A / forces everything before it to be positional.

python
def connect(host, port, *, timeout=10):
    print(host, port, timeout)

connect("db.local", 5432, timeout=5)
# connect("db.local", 5432, 5) would be an error

This is why you see calls like sorted(items, key=..., reverse=True) and never sorted(items, f, True).

Practice

  1. Write average(*nums) that returns the mean of any number of values and returns 0 for no values.
  2. Write make_tag(name, **attrs) that returns an HTML tag string, so make_tag("a", href="/x", id="l") gives <a href="/x" id="l">.
  3. Rewrite power so that the exponent must be given by keyword.