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
.