https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3
Let us first understand what are positional arguments and keyword arguments. Below is an example of function definition with Positional arguments.
def test(a,b,c):
print(a)
print(b)
print(c)
test(1,2,3)
#output:
1
2
3
So this is a function definition with positional arguments. You can call it with keyword/named arguments as well:
def test(a,b,c):
print(a)
print(b)
print(c)
test(a=1,b=2,c=3)
#output:
1
2
3
Now let us study an example of function definition with keyword arguments:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------
You can call this function with positional arguments as well:
def test(a=0,b=0,c=0):
print(a)
print(b)
print(c)
print('-------------------------')
test(1,2,3)
# output :
1
2
3
---------------------------------
So we now know function definitions with positional as well as keyword arguments.
Now let us study the '*' operator and '**' operator.
Please note these operators can be used in 2 areas:
a) function call
b) function definition
The use of '*' operator and '**' operator in function call.
Let us get straight to an example and then discuss it.
def sum(a,b): #receive args from function calls as sum(1,2) or sum(a=1,b=2)
print(a+b)
my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}
# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple) # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list) # becomes same as sum(1,2) after unpacking my_list with '*'
sum(**my_dict) # becomes same as sum(a=1,b=2) after unpacking by '**'
# output is 3 in all three calls to sum function.
So remember
when the '*' or '**' operator is used in a function call -
'*' operator unpacks data structure such as a list or tuple into arguments needed by function definition.
'**' operator unpacks a dictionary into arguments needed by function definition.
Now let us study the '*' operator use in function definition. Example:
def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
sum = 0
for a in args:
sum+=a
print(sum)
sum(1,2,3,4) #positional args sent to function sum
#output:
10
In function definition the '*' operator packs the received arguments into a tuple.
Now let us see an example of '**' used in function definition:
def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
sum=0
for k,v in args.items():
sum+=v
print(sum)
sum(a=1,b=2,c=3,d=4) #positional args sent to function sum
In function definition The '**' operator packs the received arguments into a dictionary.
So remember:
In a function call the '*' unpacks data structure of tuple or list into positional or keyword arguments to be received by function definition.
In a function call the '**' unpacks data structure of dictionary into positional or keyword arguments to be received by function definition.
In a function definition the '*' packs positional arguments into a tuple.
In a function definition the '**' packs keyword arguments into a dictionary.