LECTURE NOTE 8-
*ARGS and **KWARGS IN PYTHON COSC 424-INSY 404
By: Prof. Eze, M.O.
Babcock University, Nigeria.
It is a well-known fact, that in Python and other programming languages, and even in Mathematics,
the number of parameters in a function’s definition is expected to match the number of arguments
used for function calls. A deviation from this rule occurs when one uses the special arguments
called *args and **kwargs. Before delving into studies of *args and **kwargs, its important to
understand the concepts of Positional and Keyword arguments.
POSITIONAL vs KEYWORD ARGUMENTS
Suppose you have two Python functions (pyfun1 and pyfun2) defined as follows:
# Python Program Name: genterst10.py
def pyfun1 (x, y, z):
print ("This function sums the three numbers: ",x,y,z)
return x+y+z
print (pyfun1(10, 5, 2))
def pyfun2 (x=None, y=20, z=1):
print ("This second function sums the three numbers: ",x,y,z)
return x+y+z
print (pyfun2(x=7, y=4, z=3))
RESULT:
Thus function sums the three numbers: 10 5 2
17
This second function sums the three numbers: 7 4 3
14
EXPLANATION:
The first function pyfun1 is used to demonstrate positional arguments. For instance, the function
call pyfun1 (10,5,2) demands a one-to-one mapping in line with function definition. In other
words, the function parameters take values x➔ 10, y➔5 and z➔2 in that order. Any effort to call
the function with more or less than three arguments will lead to an error message.
1
EXAMPLE:
The function call print (pyfun1(10, 5)) will result in an error message TypeError: pyfun1()
missing 1 required positional argument: 'z'. In a similar way, the function call print
(pyfun1(10, 5,2,3)) results in an error message “TypeError: pyfun1() takes 3 positional
arguments but 4 were given”.
The second function pyfun2 demonstrates how keyword arguments work. In this case, the
arguments are given keywords eg. is used to demonstrate positional arguments. For instance, the
function definition pyfun2 (x=None, y=20, z=1) and function call pyfun2(x=7, y=4, z=3) contain
key words x, y and z. During the definition, the keyword parameters are given initial/default
values. The implication is that if for any reason no value was supplied during function calls, the
initial values take effect. As you can seem, during function call, the keywords were given values
quite different from the initial values. Again, note that since the key words have values, they could
appear in the call statement in any order eg. pyfun2 (x=7, y=4, z=3) or pyfun2 (y=4,x=7,z=3) or
pyfun2(z=3, y=4, x=7), and so on.
THE SPLAT OPERATOR:
The term “splatting” in python relates to spreading, unpacking or explosion. In other words, you
splat a sequence by unpacking all its content inside another one. In Python, the asterisk is used as
a splat operator. Example:
# Demonstrating Python Splat Operator
x=[20,1,90,5,8]
y=[6,50,12, 8]
w=[100,100,*x]
print (w)
z=[60,60,60,*y,70,70,70,*x]
print(z)
OUTPUT:
[100, 100, 20, 1, 90, 5, 8]
[60, 60, 60, 6, 50, 12, 8, 70, 70, 70, 20, 1, 90, 5, 8]
2
*ARGS and **KWARGS
With the knowledge of the splat operator (*), and how Python unpacks sequence of values in
functions, we can now discuss the subject matter. The term *args stands for variable number of
arguments, while ** stands for variable number of keyword arguments. The implication is that
when any of *args and **kwargs appear in function definitions, the function calls could involve
any number of arguments, though the later uses keyword arguments.
QUESTION:
Create a function that accepts and displays Surname, RegNumber, and the list of scores for a
student in various class tests. The number of tests is not precisely known at present, and thus could
vary.
SOLUTION:
def testscore(surname, regnum, *scores):
print(f"SURNAME: {surname}")
print(f"REG NUMBER: {regnum}")
for score in scores:
print(score)
testscore ("Danladi","01-2011-7777", 64,30,79,84,55)
testscore ("Ifeanyi","02-2013-4000", 73,69,61)
testscore ("Lokodan","03-2012-9898", 90,87,52,70,68,47,19)
testscore ("Farading","04-2015-5319", 64,30)
OUTPUT:
SURNAME: Danladi
REG NUMBER: 01-2011-7777
64
30
79
84
55
SURNAME: Ifeanyi
REG NUMBER: 02-2013-4000
73
69
61
SURNAME: Lokodan
REG NUMBER: 03-2012-9898
90
87
52
70
68
47
19
SURNAME: Farading
REG NUMBER: 04-2015-5319
64
30
3
IMPORTANT NOTE:
1. When there are more than one type of arguments in a function call, the following order
must be maintained:
a. positional arguments
b. varied arguments (*args)
c. keyword varied arguments (**kwargs)
Example: functcall(vara, *args, **kwargs)
If one deviates from this rule, system will send an eror message.
2. Thus, one cannot place **kwargs before *args.
3. You can use args and kwargs in for…loop statement. Example:
def sum(*args):
s=0
for i in args:
s += i
print("sum is", s)
sum(1, 2, 3, 4, 5, 7, 8, 9, 10)
OUTPUT:
sum is 49
4. The name *args is just a convention. In other words, one can use any valid identifier,
example *score, *boys, *women, etc.
USE OF **KWARGS:
On the other hands, *kwargs allows one to pass variable number of keyword arguments in a
function call.
EXAMPLE:
def demokwargs(**kwargs):
for x, y in kwargs.items():
print(x, y)
demokwargs(Name='Samuel', Height='6.8feet', Colour='Tinted Black', Sex='Male', Age=24)
OUTPUT:
Name Samuel
Height 6.8feet
Colour Tinted Black
Sex Male
Age 24
4
QUESTION:
Write a method that will use **kwargs to keep tract of the books in the library. Precaution must
be taken to ensure that the keywords data supplied is not empty. To program should be tested using
the following three books: Physics by Dr. Jaa, Maths by Prof. Dan, English by Dr. Roy.
#kwargs2.py
def books(**kwargs):
if kwargs is not None:
for key, value in kwargs.items():
print ("%s : %s" %(key,value))
books(bk1= "Physics by Dr. Jaa", bk2="Maths by Prof. Dan", bk3="English by Dr. Roy")
OUTPUT:
bk1 : Physics by Dr. Jaa
bk2 : Maths by Prof. Dan
bk3 : English by Dr. Roy
QUESTION:
Now carefully study the follow two concatenation programs and explain difference in output. Both
programs (contact1.py and concat2.py) use **kwargs and a For-Loop to effect concatenation
using contents of a dictionary data structure.
# concat1.py
def concat1(**kwargs):
output = ""
# Here is a Concatenation For - Loop
for arg in kwargs.values():
output += arg
return output
# concat2.py
def concat2(**kwargs):
output = ""
# Here is a Concatenation For - Loop
for arg in kwargs:
output += arg
return output
5
ANSWER:
Run the two programs. It is obvious that the two programs have different outputs. While the first
concatenates the values of the dictionary structure, the second concatenates the keys.
>>> print(concat1(a="First.", b="Second.", c="Third.", d="Fourth."))
OUTPUT1:
First.Second.Third.Fourth.
>>> print(concat2(a="First.", b="Second.", c="Third.", d="Fourth."))
OUTPUT2:
abcd
QUESTION:
Which of the following function definitions (progA.py and progB.py) is correct, and which is
wrong? Mention reason for your view.
# progA.py
def babfunction(a, b, *args, **kwargs):
pass
# progB.py
def babfunction (a, b, **kwargs, *args):
pass
ANSWER:
The first one progA.py is correct, while the second one progB.py is wrong. The reason is that *args
must come before **kwargs in any function where both are present.
QUESTION:
Explain what is wrong with the following function definition, the re-write into correct format.
# progC.py
def parafunction(a, *args, **kwargs, b):
pass
6
ANSWER:
The reason is that the positional arguments must come before *args and **kwargs in any function
definition or call. The correct format is as follows:
# progC.py
def parafunction (a, b, *args, **kwargs):
pass
QUESTION:
Explain the result of the following unpacking operation, and why it is so.
# unpack1.py
xyz = [30, 77, 92, 84]
print(*xyz)
ANSWER:
The result is as follows:
30 77 92 84
As shown, the unpack operator * unpacks the list xyz. The moment this is done, the print function
prints the content of the list, rather than the original list.
QUESTION:
Given the following function, create a list called myList and demonstrate how to make a function
call involving unpacking operation.
# Demonstrating Unpacking
def adder(a, b, c):
print(a + b + c)
SOLUTION:
Since the function parameters are not variable, then the input list should be exactly the number
items specified by function parameter definition. Example is myList = [10, 5,90]. The function
call incorporating unpacking operation is
adder (*myList).
7
QUESTION:
Given the following program. What will be the outputs a, b, and c. Explain the reason for the
output based on your understanding of the unpacking operator *..
cisgroup = [11, 2, 39, 4, 5, 16]
x, *y, z = cisgroup
print(x)
print(y)
print(z)
ANSWER:
11
[2, 39, 4, 5]
16
Explanation: The cisgroup list has 6 items. The first variable is assigned to x, the last to z. The
unpacked values all represent y.