Python args kwargs
The *args and **kwargs syntax lets a function accept any number of extra positional or keyword arguments without knowing how many will arrive.
Why variable arguments exist
Sometimes you cannot know in advance how many values a function will receive. A function that adds numbers might get two values one time and ten the next. Python solves this with two special markers in the parameter list: a single asterisk collects extra positional arguments, and a double asterisk collects extra keyword arguments.
Collecting positional arguments with *args
When you prefix a parameter with a single asterisk, Python gathers all remaining positional arguments into a tuple. The name args is only a convention; the asterisk is what does the work. You can then loop over that tuple like any other sequence.
Summing any number of values
def total(*numbers):
result = 0
for n in numbers:
result += n
return result
print(total(3, 5)) # 8
print(total(1, 2, 3, 4, 5)) # 15
print(total()) # 0Collecting keyword arguments with **kwargs
A parameter prefixed with two asterisks gathers all extra keyword arguments into a dictionary, where each key is the argument name and each value is what was passed. This is handy for functions that accept flexible options or settings.
Handling named options as a dictionary
def describe(**details):
for key, value in details.items():
print(key + ": " + str(value))
describe(name="Leo", age=30, city="Pune")
# name: Leo
# age: 30
# city: PuneCombining everything and unpacking
You can mix regular parameters, *args, and **kwargs in one definition, but they must appear in that order. The same asterisks also work in reverse: when calling a function, you can use * to spread a list into positional arguments and ** to spread a dictionary into keyword arguments.
Order of parameters and unpacking a call
def report(title, *scores, **info):
print(title, scores, info)
report("Results", 90, 85, source="exam")
# Results (90, 85) {'source': 'exam'}
values = [90, 85]
extra = {"source": "exam"}
report("Results", *values, **extra)
# Results (90, 85) {'source': 'exam'}