Home > Back-end >  inheritance TypeError: __init__() takes from 1 to 2 positional arguments but 8 were given
inheritance TypeError: __init__() takes from 1 to 2 positional arguments but 8 were given

Time:05-14

I am trying to follow an example related to inheritance from a Python OOP book. However, I am facing an error.

from __future__ import annotations

class ContactList(list["Contact"]):
    def search(self, name: str) -> list["Contact"]:
        matching_contacts: list["Contact"] = []

        for contact in self:
            if name in contact.name:
                matching_contacts.append(contact)
        return matching_contacts


class Contact:
    all_contacts = ContactList()
    
    def __init__(self, /, name: str = "", email: str = "", **kwargs) -> None:
        super().__init__(**kwargs)
        self.name = name
        self.email = email
        self.all_contacts.append(self)

    def __repr__(self) -> str:
        return f"{self.__class__.__name__}(" f"{self.name!r}, {self.email!r}" f")"


class AddressHolder:
    def __init__(self, /, street: str = "", city: str = "", state: str = "", code: str = "", **kwargs) -> None:
        super().__init__(**kwargs)
        self.street = street
        self.city = city
        self.state = state
        self.code = code


class Friend(Contact, AddressHolder):
    def __init__(self, /, phone: str = "", **kwargs) -> None:
        super().__init__(**kwargs)
        self.phone = phone


f1 = Friend("Dusty", "[email protected]", "Elm Street", "New York City", "New York", "1100", "123-456-7890")

print(f1)

The error is:

Traceback (most recent call last):
  File "test.py", line 41, in <module>
    f1 = Friend("Dusty", "[email protected]", "Elm Street", "New York City", "New York", "1100", "123-456-7890")
TypeError: Friend.__init__() takes from 1 to 2 positional arguments but 8 were given

CodePudding user response:

Since Friend is calling super().__init__(**kwargs) and inherits from both AddressHolder and Contact, you want all the arguments needed by the initialisers of those classes to be supplied through kwargs (i.e., as keyword arguments). You can see how this works by printing kwargs inside of Friend.__init__ and by having your parameters passed with keywords:

class Friend(Contact, AddressHolder):
    def __init__(self, /, phone: str = "", **kwargs) -> None:
        
        # Added line.
        print(kwargs)
        
        super().__init__(**kwargs)
        self.phone = phone

# Passing phone as positional argument, all the rest as keyword arguments.
f1 = Friend("123-456-7890", name="Dusty", email="[email protected]", street="Elm Street", city="New York City", state="New York", code="1100")

print(f1)
{'name': 'Dusty', 'email': '[email protected]', 'street': 'Elm Street', 'city': 'New York City', 'state': 'New York', 'code': '1100'}
Friend('Dusty', '[email protected]')

kwargs would collect all the keyword arguments you supply that are not specified in the signature of Friend.__init__(). Since you don't have keyword arguments, all the keyword arguments end up in kwargs. super().__init__(**kwargs) will call Contact.__init__(**kwargs) and AddressHolder.__init__(**kwargs), supplying all the arguments they need to create the instances.

You passed all your arguments as positional, i.e. without a keyword. Your error is telling you this does not correspond to the signature of Friend.__init__(), that only allows two positional arguments (self and phone). The error disappears when you put the keywords because all those arguments end up in kwargs.

  • Related