Introduction: Python Argument Unpacking With Positional-Only and Keyword-Only Parameters
Python Argument Unpacking With Positional-Only and Keyword-Only Parameters is useful when you need to control how unpacked values are passed to function parameters. These parameter restrictions determine whether an argument must be passed by position or by keyword.
When argument unpacking is used with these parameters, the unpacking operator must match the way the parameter accepts its value: * supplies positional arguments, while ** supplies keyword arguments.
The following sections show how argument unpacking works with each parameter type and how the two unpacking operators work together with mixed parameter types.
Unpacking Into Positional-Only Parameters
A positional-only parameter must receive its value by position. Therefore, * can unpack values into positional-only parameters, but ** cannot supply them as keyword arguments.
The / syntax marks parameters as positional-only, meaning they cannot be passed by keyword.
Using * With Positional-Only Parameters
def calculate_total(price, quantity, /):
return price * quantity
values = [50, 3]
print(calculate_total(*values))
# Output:
150
Explanation: The / marks price and quantity as positional-only parameters. The *values expression supplies their values by position.
Why ** Cannot Supply Positional-Only Parameters
The ** operator creates keyword arguments, but positional-only parameters cannot receive values by keyword.
def calculate_total(price, quantity, /):
return price * quantity
values = {
"price": 50,
"quantity": 3
}
calculate_total(**values)
# Error:
TypeError
Explanation: The dictionary keys become keyword argument names. However, price and quantity are positional-only, so Python raises a TypeError.
Unpacking Into Keyword-Only Parameters
A keyword-only parameter must receive its value by keyword. Therefore, ** can unpack a dictionary into keyword-only parameters, while * cannot supply them positionally.
The * syntax marks the parameters that follow it as keyword-only, meaning they must be passed by keyword.
Using ** With Keyword-Only Parameters
def create_user(*, name, age):
print(name, age)
details = {
"name": "Alice",
"age": 25
}
create_user(**details)
# Output:
Alice 25
Explanation: The **details expression creates keyword arguments from the dictionary. Python matches the keys "name" and "age" with the corresponding keyword-only parameters.
Why * Cannot Supply Keyword-Only Parameters
The * operator creates positional arguments, but keyword-only parameters cannot receive values by position.
def create_user(*, name, age):
print(name, age)
values = ["Alice", 25]
create_user(*values)
# Error:
TypeError: create_user() takes 0 positional arguments but 2 were given
Explanation: The *values expression supplies two positional arguments, but name and age are keyword-only parameters. Python therefore raises a TypeError.
Matching the Unpacking Operator to Positional-Only and Keyword-Only Parameters
Python Argument Unpacking With Positional-Only and Keyword-Only Parameters requires the unpacking operator to match the way each parameter accepts its value. The table below shows which operator works with each parameter type.
| Parameter Type | * Unpacking |
** Unpacking |
|---|---|---|
| Regular | Works | Works |
| Positional-only | Works | Does not work |
| Keyword-only | Does not work | Works |
Key rule: * supplies positional arguments, while ** supplies keyword arguments.
Using * and ** With Mixed Parameter Types
Python Argument Unpacking With Positional-Only and Keyword-Only Parameters can also be used alongside regular parameters in the same function. In such cases, * and ** can supply the values in the required way.
def process(a, /, b, *, c):
print(a, b, c)
values = [10, 20]
details = {
"c": 30
}
process(*values, **details)
# Output:
10 20 30
Explanation: The / makes a positional-only, while the * in the function definition makes c keyword-only. The *values expression supplies 10 and 20 as positional arguments, so they are assigned to a and b. The **details expression supplies c=30 as a keyword argument.
This allows both unpacking operators to be used in the same function call when different parameters require different argument types.
Key Takeaways: Argument Unpacking With Positional-Only and Keyword-Only Parameters
The following key takeaways summarize Python Argument Unpacking With Positional-Only and Keyword-Only Parameters:
*unpacks an iterable into positional arguments.**unpacks a dictionary into keyword arguments.- Positional-only parameters accept values only through positional arguments, so
*can supply them but**cannot. - Keyword-only parameters accept values only through keyword arguments, so
**can supply them but*cannot. - The
/syntax defines positional-only parameters, while*can define keyword-only parameters. - When a function contains different parameter types, the unpacking operator must match how each parameter accepts its value.