2022-05-27 06:47:27 -05:00
# About
For the basics on function arguments, please see the [function concept][function concept].
## Parameter Names
Paramater names, like variable names, must start with a letter or underscore and may contain letters, underscores, or numbers.
Parameter names should not contain spaces or punctuation.
## Positional Arguments
2022-05-31 17:31:10 -05:00
Positional arguments are values passed to a function in the same order as the parameters which bind to them.
2022-05-31 21:19:53 -05:00
Positional arguments can optionally be passed by using their parameter name.
2022-05-27 06:47:27 -05:00
2022-05-31 21:15:21 -05:00
Following is an example of positional arguments being passed by position and by their parameter name:
2022-05-27 06:47:27 -05:00
```python
2022-05-30 15:22:31 -05:00
>>> def concat(greeting, name):
... return f"{greeting}{name}"
2022-05-29 06:49:57 -05:00
...
2022-05-31 16:51:23 -05:00
# Passing data to the function by position.
2022-05-27 06:47:27 -05:00
>>> print(concat("Hello, ", "Bob"))
2022-05-31 16:51:23 -05:00
2022-05-27 06:47:27 -05:00
Hello, Bob
2022-06-01 11:37:26 -05:00
...
# Passing data to the function using the parameter name.
2022-05-30 15:22:31 -05:00
>>> print(concat(name="Bob", greeting="Hello, "))
2022-06-01 11:37:26 -05:00
2022-05-27 06:47:27 -05:00
Hello, Bob
```
The first call to `concat` passes the arguments by position.
2022-05-28 13:27:19 -05:00
The second call to `concat` passes the arguments by name, allowing their positions to be changed.
2022-05-27 06:47:27 -05:00
2022-05-27 06:56:56 -05:00
Note that positional arguments cannot follow keyword arguments.
This
```python
2022-05-30 15:22:31 -05:00
>>> print(concat(greeting="Hello, ", "Bob"))
2022-05-27 06:56:56 -05:00
```
results in this error:
```
SyntaxError: positional argument follows keyword argument
```
2022-06-03 08:31:15 -05:00
Requiring positional-only arguments for function calls can be done through the use of the `/` operator in the parameter list.
2022-05-27 06:47:27 -05:00
Following is an example of positional-only arguments:
```python
2022-06-01 11:47:02 -05:00
# Parameters showing a position-only operator.
2022-05-30 15:22:31 -05:00
>>> def concat(greeting, name, /):
... return f"{greeting}{name}"
2022-06-01 11:47:02 -05:00
2022-05-29 06:49:57 -05:00
...
2022-05-27 06:47:27 -05:00
>>> print(concat("Hello, ", "Bob"))
Hello, Bob
2022-06-01 11:47:53 -05:00
...
# Call to the function using keyword arguments.
2022-05-30 15:22:31 -05:00
>>> print(concat(name="Bob", greeting="Hello, "))
2022-05-27 06:47:27 -05:00
Traceback (most recent call last):
2022-05-30 15:22:31 -05:00
print(concat(name="Bob", greeting="Hello, "))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting, name'
2022-05-27 06:47:27 -05:00
2022-06-01 11:47:53 -05:00
2022-05-27 06:47:27 -05:00
```
## Keyword Arguments
2022-06-01 12:02:38 -05:00
Keyword arguments use the parameter name when calling a function.
Keyword arguments can optionally be referred to by position.
2022-05-27 06:47:27 -05:00
2022-06-01 12:02:38 -05:00
Following is an example of keyword arguments being referred to by their parameter name and by position:
2022-05-27 06:47:27 -05:00
```python
2022-06-01 12:02:38 -05:00
>>> def concat(greeting, name):
2022-05-30 15:22:31 -05:00
... return f"{greeting}{name}"
2022-05-29 06:49:57 -05:00
...
2022-06-01 12:02:38 -05:00
# Function call using parameter names as argument keywords.
2022-05-30 15:22:31 -05:00
>>> print(concat(name="Bob", greeting="Hello, "))
2022-05-27 06:47:27 -05:00
Hello, Bob
2022-06-01 12:02:38 -05:00
...
# Function call with positional data as arguments.
2022-05-27 06:47:27 -05:00
>>> print(concat("Hello, ", "Bob"))
Hello, Bob
```
2022-06-03 08:36:51 -05:00
Requiring keyword-only arguments for function calls can be done through the use of the `*` operator in the parameter list.
2022-05-27 06:47:27 -05:00
Following is an example of keyword-only arguments:
```python
2022-06-01 12:06:38 -05:00
# Function definition requiring keyword-only arguments.
>>> def concat(*, greeting, name):
2022-05-30 15:22:31 -05:00
... return f"{greeting}{name}"
2022-05-29 06:49:57 -05:00
...
2022-06-01 12:06:38 -05:00
# Keyword arguments can be in an arbitrary order.
2022-05-30 15:22:31 -05:00
>>> print(concat(name="Bob", greeting="Hello, "))
2022-05-27 06:47:27 -05:00
Hello, Bob
2022-06-01 12:06:38 -05:00
...
# Calling the function with positional data raises an error.
2022-05-27 06:47:27 -05:00
>>> print(concat("Hello, ", "Bob"))
Traceback (most recent call last):
print(concat("Hello, ", "Bob"))
TypeError: concat() takes 0 positional arguments but 2 were given
2022-06-01 12:06:38 -05:00
2022-05-27 06:47:27 -05:00
```
2022-06-03 08:35:50 -05:00
## Default Argument Values
Default values for one or more arguments can be supplied in the parameter list.
This allows the function to be called with _fewer_ arguments if needed.
Default values can be overridden by calling the function with a new argument value, overriding the default:
```python
# Function with default argument values.
>>> def concat(greeting, name="you", punctuation="!"):
... return f"{greeting}, {name}{punctuation}"
...
>>> print(concat("Hello"))
Hello, you!
# Overriding the default values
>>> print(concat("Hello", name="Bob", punctuation="."))
Hello, Bob.
2022-06-03 10:00:22 -05:00
```
2022-05-27 06:47:27 -05:00
## Positional or Keyword Arguments
Arguments can be positional or keyword if neither the `/` nor `*` operators are used in the parameter definitions.
2022-06-01 11:53:48 -05:00
Alternately, the positional-or-keyword arguments can be placed between the positional-only parameters on the left and the keyword-only parameters on the right.
2022-05-27 06:47:27 -05:00
2022-05-27 07:04:45 -05:00
Following is an example of positional-only, positional-or-keyword, and keyword-only arguments:
2022-05-27 06:47:27 -05:00
```python
2022-06-01 12:09:27 -05:00
# Position-only argument followed by position-or-keyword, followed by keyword-only.
>>> def concat(greeting, /, name, *, ending):
2022-05-30 15:22:31 -05:00
... return f"{greeting}{name}{ending}"
2022-05-29 06:49:57 -05:00
...
2022-05-30 15:22:31 -05:00
>>> print(concat("Hello, ", "Bob", ending="!"))
2022-05-27 06:47:27 -05:00
Hello, Bob!
2022-05-30 15:22:31 -05:00
>>> print(concat("Hello, ", name="Bob", ending="!"))
2022-05-27 06:47:27 -05:00
Hello, Bob!
2022-06-01 12:09:27 -05:00
...
2022-05-30 15:22:31 -05:00
>>> print(concat(greeting="Hello, ", name="Bob", ending="!"))
2022-05-27 06:47:27 -05:00
Traceback (most recent call last):
2022-05-30 15:22:31 -05:00
print(concat(greeting="Hello, ", name="Bob", ending="!"))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting'
2022-05-27 06:47:27 -05:00
2022-06-01 15:58:24 -05:00
```
2022-05-27 06:47:27 -05:00
## `*args`
2022-05-28 10:22:12 -05:00
Code examples will often use a function definition something like the following:
2022-05-27 09:50:51 -05:00
```python
2022-05-28 10:22:12 -05:00
def my_function(*args, **kwargs):
2022-05-27 09:50:51 -05:00
# code snipped
```
2022-06-01 12:14:02 -05:00
`*args` is a two-part name that represents a `tuple` with an indefinite number of separate positional arguments, also known as a [`variadic argument` ][variadic argument].
2022-06-01 12:19:40 -05:00
`args` is the name given to the `tuple` of arguments, but it could be any other valid Python name, such as `my_args` , `arguments` , etc.
2022-05-27 09:50:51 -05:00
The `*` is the operator which transforms the group of separate arguments into a [`tuple` ][tuple].
2022-06-02 06:27:10 -05:00
2022-06-03 09:50:26 -05:00
~~~~exercism/note
2022-06-02 06:45:53 -05:00
If you have ever [unpacked a tuple][unpack a tuple] you may find the `*` in `*args` to be confusing.
2022-06-03 08:36:25 -05:00
The `*` in a _parameter_ definition, instead of unpacking a tuple, converts one or more positional arguments _into_ a tuple.
2022-06-02 06:47:13 -05:00
We say that the `*` operator is [overloaded], as it has different behavior in different contexts.
2022-06-02 06:45:53 -05:00
For instance, `*` is used for multiplication, it is used for unpacking, and it is used to define an arbitrary number of positional parameters.
2022-06-03 09:50:26 -05:00
~~~~
2022-06-02 06:27:10 -05:00
2022-05-27 09:50:51 -05:00
Since a tuple can be iterated, `args` can be passed to any other function which takes an iterable.
2022-05-28 10:22:12 -05:00
Although `*args` is commonly juxtaposed with `**kwargs` , it doesn't have to be.
2022-05-27 09:50:51 -05:00
2023-10-27 22:30:30 +02:00
Following is an example of an arbitrary number of values being passed to a function:
2022-06-03 09:15:21 -05:00
```python
>>> def add(*args):
# args is passed to the sum function, which takes an iterable
... return sum(args)
...
>>> print(add(1, 2, 3))
6
```
If `*args` follows one or more positional arguments, then `*args` will be what is left over after the positional arguments.
2023-10-27 22:30:30 +02:00
Following is an example of an arbitrary number of values being passed to a function after a positional argument:
2022-06-03 09:15:21 -05:00
```python
>>> def add(first, *args):
# first will be 1, leaving the values 2 and 3 in *args
... return first + sum(args)
...
>>> print(add(1, 2, 3))
6
```
If one or more default arguments are defined after `*args` they are separate from the `*args` values.
2023-10-27 22:30:30 +02:00
To put it all together is an example of an arbitrary number of values being passed to a function that also has a positional argument and a default argument:
2022-05-27 09:50:51 -05:00
```python
>>> def add(first, *args, last=0):
2022-05-29 06:49:57 -05:00
... return first + sum(args) + last
...
2022-05-27 09:50:51 -05:00
>>> print(add(1, 2, 3))
6
>>> print(add(1, 2, 3, last=4))
10
2022-06-02 06:27:10 -05:00
# This uses the unpacking operator * to separate the list elements into positional arguments.
2022-06-02 06:45:53 -05:00
# It does not have the same behavior as the * in *args.
2022-05-27 09:50:51 -05:00
>>> print(add(*[1, 2, 3]))
6
```
2023-10-27 22:30:30 +02:00
Note that when an argument is already in an iterable, such as a tuple or list, it needs to be unpacked before being passed to a function that takes an arbitrary number of separate arguments.
2022-06-03 08:33:36 -05:00
This is accomplished by using `*` , which is the [unpacking operator][unpacking operator].
2022-06-03 08:32:47 -05:00
`*` in this context _unpacks_ the container into its separate elements which are then transformed by `*args` into a tuple.
Where there are only positional arguments, the unpacking action must result in the same number of arguments as there are formal parameters.
2022-05-27 09:50:51 -05:00
Without unpacking the list passed into `add` , the program would error.
```python
>>>> def add(first, *args, last=0):
2022-05-29 06:49:57 -05:00
... return first + sum(args) + last
...
2022-05-27 09:50:51 -05:00
>>>> print(add([1, 2, 3]))
Traceback (most recent call last):
print(add([1, 2, 3]))
return first + sum(args) + last
TypeError: can only concatenate list (not "int") to list
```
2022-05-28 10:22:12 -05:00
## `**kwargs`
`**kwargs` is a two-part name that represents an indefinite number of separate [key-value pair][key-value] arguments.
`kwargs` is the name of the group of arguments and could be any other name, such as `my_args` , `arguments` , etc.
2022-06-01 15:10:44 -05:00
The `**` transforms the group of named arguments into a [`dictionary` ][dictionary] of `{argument name: argument value}` pairs.
2022-05-28 10:22:12 -05:00
Since a dictionary can be iterated, `kwargs` can be passed to any other function which takes an iterable.
Although `**kwargs` is commonly juxtaposed with `*args` , it doesn't have to be.
2023-10-27 22:30:30 +02:00
Following is an example of an arbitrary number of key-value pairs being passed to a function:
2022-05-28 10:22:12 -05:00
```python
>>> def add(**kwargs):
2022-05-29 06:49:57 -05:00
... return sum(kwargs.values())
...
2022-05-28 10:22:12 -05:00
>>> print(add(one=1, two=2, three=3))
6
```
2022-06-01 15:11:53 -05:00
Note that the `dict.values()` method is called to iterate through the `kwargs` dictionary values.
2022-05-28 10:22:12 -05:00
When iterating a dictionary the default is to iterate the keys.
2023-10-27 22:30:30 +02:00
Following is an example of an arbitrary number of key-value pairs being passed to a function that then iterates over `kwargs.keys()` :
2022-05-28 10:22:12 -05:00
```python
>>> def concat(**kwargs):
2022-06-01 15:15:06 -05:00
# Join concatenates the key names from `kwargs.keys()`
2022-05-29 06:49:57 -05:00
... return " ".join(kwargs)
...
2022-05-28 10:22:12 -05:00
>>> print(concat(one=1, two=2, three=3))
one two three
2022-06-01 15:46:36 -05:00
```
2022-05-27 06:47:27 -05:00
[default arguments]: https://www.geeksforgeeks.org/default-arguments-in-python/
2022-05-28 10:22:12 -05:00
[dictionary]: https://www.w3schools.com/python/python_dictionaries.asp
2022-05-27 06:47:27 -05:00
[function concept]: ../functions/about.md
2022-05-28 10:22:12 -05:00
[key-value]: https://www.pythontutorial.net/python-basics/python-dictionary/
2022-06-02 06:27:10 -05:00
[overloaded]: https://www.geeksforgeeks.org/operator-overloading-in-python/
2022-05-27 09:50:51 -05:00
[tuple]: https://www.w3schools.com/python/python_tuples.asp
2022-06-02 06:27:10 -05:00
[unpack a tuple]: https://www.geeksforgeeks.org/unpacking-a-tuple-in-python/
2022-05-27 09:50:51 -05:00
[unpacking operator]: https://docs.python.org/3/tutorial/controlflow.html#unpacking -argument-lists
2022-06-01 12:15:10 -05:00
[variadic argument]: https://en.wikipedia.org/wiki/Variadic_function