TypeError : __init__() takes 1 positional argument but X were given

This post is about one of the type errors that occur when using classes in Python.

Table of Contents

For more information about argument types and parameter types, see Argument Types in Python Functions, Parameter Types in Python Functions.


Explanation of the Error

What does the error message mean?

This error points to the line where we are trying to create a new instance of the class. In short, the following message means that the arguments you are using do not match the parameters of the __init__ method.

...
    class_instance = MyClass(<some arguments here>)
TypeError : MyClass.__init__() takes 1 positional argument but X were given

The __init__ method has one required parameter in its signature. By convention, this parameter is usually called "self". The current instance of the class is the value of the "self" parameter.

def __init__(self):
    pass

This 1 positional argument in the error message refers to an instance of the class.

X is the total number of arguments (values) passed to __init__, including the instance.

"But X were given" means you added unnecessary positional arguments. There are no parameters in the __init__ method that would take these values.

There is also one special case with keyword arguments, see Cases Where an Error Happens.


Cases Where an Error Happens

There are two typical cases when this TypeError occurs:

In the first case, we passed arguments to __init__ for which no parameters were specified in the method signature.

In the second case, part of the method arguments must be only keyword arguments. Arguments were passed incorrectly.


1) The error occurs when the __init__ method of the class does not accept any additional values other than the instance.

Code:
class A:
    def __init__(self): # <-- one parameter is specified
        pass

# 2 values (arguments): instance and "excess"
a = A("excess") # <-- must be empty
# TypeError: A.__init__() takes 1 positional argument but 2 were given

Here, __init__ takes 1 positional argument - an instance of the class. The 2 positional arguments in the error message refer to instance and "excess".


2) The error occurs when the __init__ method accepts only one positional argument, all other arguments are keyword arguments.

Keyword arguments mean that you need to pair a parameter name with a value.

In the following example, the __init__ method contains keyword-only parameters. Keyword-only parameters can be specified by including an asterisk (*) in the list of parameters. param2 and param3 are such parameters.

All arguments matching the parameters listed after * must be keyword arguments.

class A:
    def __init__(self, *, param2, param3):
        pass

# one positional and two keyword arguments - OK
a = A(param2="some value", param3="other value")

# three positional arguments: instance, "some value", "other value"
a = A("some value", "other value")
# TypeError: A.__init__() takes 1 positional argument but 3 were given

# another version of the same error
a = A("some value", param3="other value")
# TypeError: A.__init__() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given

The next example is similar to the previous one. **kwargs in a function signature indicate that the function can take arbitrary keyword arguments.

The first positional argument is always an instance of the class (the value for the self parameter). Except for the first argument, all other arguments must be keyword arguments in this example.

class A:
    def __init__(self, **kwargs):
        pass

# one positional argument and one keyword argument - OK
a = A(param2="value")

# two positional arguments: instance and "value"
a = A("value")
# TypeError: A.__init__() takes 1 positional argument but 2 were given

To prevent an error, we need to specify the keyword arguments properly.


Popular posts from this blog

Tkinter Button Widget