PythonFunction Arguments

Function Arguments

Python gives you several ways to pass values into a function: by position, by keyword, or a mix of both. Since Python 3.8, you can even force certain parameters to be positional-only or keyword-only. Understanding these rules helps you write function signatures that are both flexible and hard to misuse.

Positional Arguments

Positional arguments are matched to parameters purely by their order — the first argument fills the first parameter, the second fills the second, and so on.

Python
def describe_pet(name, animal_type):
    print(f"{name} is a {animal_type}.")


describe_pet("Rex", "dog")
describe_pet("dog", "Rex")  # order matters! swapped meaning
Rex is a dog.
dog is a Rex.
Keyword Arguments

Keyword arguments are passed as name=value, matching the parameter by name instead of position. This makes the call self-documenting and lets you reorder arguments freely.

Python
def describe_pet(name, animal_type):
    print(f"{name} is a {animal_type}.")


describe_pet(animal_type="dog", name="Rex")
describe_pet(name="Milo", animal_type="cat")
Rex is a dog.
Milo is a cat.
Mixing Positional and Keyword Arguments

You can combine both styles in a single call, but positional arguments must always come before keyword arguments.

Python
def describe_pet(name, animal_type, age=1):
    print(f"{name} is a {age}-year-old {animal_type}.")


describe_pet("Rex", animal_type="dog", age=3)  # OK
describe_pet("Rex", age=3, animal_type="dog")  # OK, keyword order flexible
Rex is a 3-year-old dog.
Rex is a 3-year-old dog.
Warning
Putting a positional argument *after* a keyword argument is a `SyntaxError`: `describe_pet(name="Rex", "dog")` will fail to even run. Once you switch to keyword arguments in a call, everything after must also be keyword.
Positional-Only Parameters (`/`)

Since Python 3.8, a / in the parameter list marks everything before it as positional-only — those parameters can never be passed by keyword. This is useful when a parameter name is an implementation detail that shouldn't be part of the public API.

Python
def power(base, exponent, /):
    return base ** exponent


print(power(2, 10))          # OK — positional
print(power(base=2, exponent=10))  # TypeError: positional-only
1024
TypeError: power() got some positional-only arguments passed as keyword arguments: 'base, exponent'
Keyword-Only Parameters (`*`)

A * in the parameter list marks everything after it as keyword-only — those parameters must be passed by name. This forces callers to be explicit about what a value means, which is especially valuable for boolean flags or rarely-used options.

Python
def create_user(username, *, is_admin=False):
    role = "admin" if is_admin else "member"
    print(f"{username} created as {role}")


create_user("ada", is_admin=True)   # OK
create_user("ada", True)            # TypeError: too many positional arguments
ada created as admin
TypeError: create_user() takes 1 positional argument but 2 were given
Combining `/` and `*`

A single signature can use both markers to define three zones: positional-only, normal (either style), and keyword-only.

Python
def transfer(amount, /, account, *, note=""):
    print(f"Transferring {amount} to {account}. Note: {note or '(none)'}")


transfer(100, "checking", note="rent")
transfer(100, account="savings")
Transferring 100 to checking. Note: rent
Transferring 100 to savings. Note: (none)
Tip
If you never use `/` or `*`, every parameter defaults to being usable either positionally or by keyword — that's the common case and is fine for most functions. Reach for these markers only when you want to lock down a specific calling convention.
Argument Order Rules

Zone

Syntax marker

How it can be passed

Positional-only

before /

By position only

Positional-or-keyword

between / and * (or no markers)

By position or keyword

Keyword-only

after *

By keyword only

*args

collects extra positional args

Not addressable by name

**kwargs

collects extra keyword args

Addressable only by name, dynamically

  • In a function definition, the order must be: positional-only, then positional-or-keyword, then *args, then keyword-only, then **kwargs.

  • In a function call, all positional arguments must come before any keyword arguments.

Example
A signature using both markers to model a realistic API: a required amount passed positionally, and an explicit, keyword-only `currency` option.

Python
def charge(amount, /, *, currency="USD"):
    print(f"Charging {amount} {currency}")


charge(49.99)
charge(49.99, currency="EUR")
Charging 49.99 USD
Charging 49.99 EUR
Note
You'll meet `*args` and `**kwargs` — the tools for accepting a *variable* number of arguments — in the next lesson.