Unexpected Keyword Argument in Python

This is a Python TyperError that occurs when we try to call a function with a keyword argument that is not expected by the function. Let us reproduce the error and then see how to solve the error.

Reproducing the Error

Suppose we define the following function add() that accepts two values value1 and value2 and adds them.

def add(value1, value2):
    return value1+value2
#calling the function add()
add(value1=2, value3=3)

Output:

TypeError: add() got an unexpected keyword argument 'value3'

When calling the function add() we passed two keyword arguments value1 and value3, but the function expected value1 and value2, not value3 hence we get an error. The same error can also be generated when unexpected keyword arguments are passed to a class object. For example,

class Add():
    def __init__(self, a1, a2):
   	 self.a1 = a1
   	 self.a2 = a2
    def add_func(self):
   	 return self.a1+self.a2
# Initializing the class
s = Add(a1=3, a3=4)
#call the function add_func() on the class
print(s.add_func())

Output:

TypeError: __init__() got an unexpected keyword argument 'a3'

Arguments to a class are passed through __init__() magic/dunder function. In the above example, Add() class expected two arguments, a1 and a2, but when calling the class, unexpected argument a3 is passed hence the error.

The Solution to the Error

The primary solution to the error is to pass the keyword arguments expected by the function/class. This can be achieved in two ways.

Method 1: Pass the expected Keyword Arguments

When calling a function or class, ensure that you pass the arguments required by the function/class. In the above example, add() function should be given two arguments, value1, and value2, not value3. The same understanding should be used to fix the TypeError in the class example above.

Method 2: Using **kwargs argument

The **kwargs argument (which stands for keyword arguments) is a special argument that can be used in Python to pass various arguments to a Python function. The functions turns unexpected keyword arguments into a dictionary that can be accessed inside the function. Let’s see an example,

def add(value1, value2, **kwargs):
    print(kwargs)
    return value1+value2+kwargs["value3"]
# calling add with two extra arguments value3 and value4
print(add(value1=3, value2=3, value3=6, value4=9))

Output:

{'value3': 6, 'value4': 9}
12

The add() functions accept any number of arguments, but value1 and value2 must be among them. All the rest will be captured as a dictionary by **kwargs and can be accessed as such. For example, in the above example, we included value3 in the sum as kwargs[“value3”].

Let’s see another example. Suppose you need to construct a function to compute the average for a varied number of arguments. We can achieve this as follows:

def add(**kwargs):
    print("kwargs: ", kwargs)
    values = list(kwargs.values())
    print("values: ", values)
    return sum(values)/len(kwargs)
# calling add functions with varied number of arguments
print("Sum:", add(a1=3, a2=3, a3=6, a4=9, a6=10))

Output:

kwargs:  {'a1': 3, 'a2': 3, 'a3': 6, 'a4': 9, 'a6': 10}
values:  [3, 3, 6, 9, 10]
Sum: 6.2

In the above code snippet, add() accepts a varied number of arguments with any keywords. Inside the function, to get the average of the values passed, we extracted the values from the dictionary as kwargs.values(), summed them up then divided them by the length (number of the items) in the dictionary.

Bonus: What are Keyword and Positional arguments in Python?

Keyword arguments (also called named arguments) are arguments passed into a function with specific parameter names. These names are used to identify them inside a function. On the other hand, positional arguments are arguments that need to be included in the proper position or order – they are identified inside a function based on the order in which they appear when the function is called.

def compute_data(a, b, c):
    return (a*b)+c
# 1 and 4 are positional, c=10 is keyword
print(“Result:", compute_data(1, 4, c=10))
# 5 is positional, c=10, b=-6 are keyword
print("Result:", compute_data(5, c=10, b=-6))
# all arguments are positional
print("Result:", compute_data(0, 10, 4))

Output:

Result: 14
Result: -20
Result: 4

Notice in the above example that positional arguments are recognized by position, whereas keyword arguments are by the parameter names. As shown in the second call of compute_data(), the order in which keyword arguments occur does not matter.

Heads up: In Python, positional arguments must come before keyword arguments; otherwise, you will get a Syntax error. For instance, if you call the function compute_data() as shown below

print("Sum:", compute_data(c=0, 10, 4))

Output:

SyntaxError: positional argument follows keyword argument

Just like **kwargs in keyword arguments, you can also use the *args argument to pass a varied number of positional arguments into a function (remember to use one asterisk (*) for *args and two (**) for **kwargs). For example,

from math import prod
def multiply(*args):
    return prod(args)
print("Result: ", multiply(4, 5, 6))

Output:

Result:  120

Note: It doesn’t have to be args and kwargs, by the way – this is just the convention. You can use any other word, for example, *values or **prices. The critical thing is the asterisks.