Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 Multiple inheritance TypeError: object.__init__() takes no parameters

I'm learning multiple inheritance in Python3. I'm wondering why the case# 1 works but case# 2 doesn't. Here are my code snippets.

class ContactList(list):
    def search(self, name):
        """Return all contacts that contain the search value
        in their name."""
        matching_contacts = []
        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="", email="", **kwargs):
        super().__init__(**kwargs)
        self.name = name
        self.email = email
        Contact.all_contacts.append(self)
        print("Cotact")


class AddressHolder:
    def __init__(self, street="", city="", state="", code="", **kwargs):
        super().__init__(**kwargs)
        self.street = street
        self.city = city
        self.state = state
        self.code = code
        print("AddressHolder")


class Friend(Contact, AddressHolder):
    # case# 1
    # def __init__(self, phone="", **kwargs):
    #     self.phone = phone
    #     super().__init__(**kwargs)
    #     print("Friend")

    # case# 2
    def __init__(self, **kwargs):
        self.phone = kwargs["phone"]
        super().__init__(**kwargs)
        print("Friend")


if __name__ == "__main__":
    friend = Friend(
        phone="01234567",
        name="My Friend",
        email="[email protected]",
        street="Street",
        city="City",
        state="State",
        code="0123")

Here is the out put of the script. If I use only kwargs (case# 2) as a parameter in "Friend" that inherits "Contact" and "AddressHolder" then Python throughs error. I already tested the same type of construct without inheritance, except object, that worked perfectly.

"""
case 1#
$ python contacts.py
AddressHolder
Cotact
Friend
>>> friend.name
'My Friend'
>>> friend.phone
'01234567'
>>>
"""

"""
case 2#
$ python contacts.py
Traceback (most recent call last):
  File "contacts.py", line 55, in <module>
    code="0123")
  File "contacts.py", line 43, in __init__
    super().__init__(**kwargs)
  File "contacts.py", line 16, in __init__
    super().__init__(**kwargs)
  File "contacts.py", line 25, in __init__
    super().__init__(**kwargs)
TypeError: object.__init__() takes no parameters
>>>
"""
like image 510
picklu Avatar asked Dec 03 '25 07:12

picklu


1 Answers

Let’s take a look at the method resolution order for Friend. This will tell us in what order the constructors will be called:

>>> Friend.mro()
[<class '__main__.Friend'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>]

So let’s take a look at case 1 first. These are the original named arguments to the Friend constructor:

phone="01234567"
name="My Friend"
email="[email protected]"
street="Street"
city="City"
state="State"
code="0123"

Now, Friend.__init__ takes phone as an explicit argument and then takes the rest as a keyword argument dictionary. so kwargs is the following:

kwargs = {
    'name': "My Friend",
    'email': "[email protected]",
    'street': "Street",
    'city': "City",
    'state': "State",
    'code': "0123",
}

Next, Contact.__init__ is called which takes the arguments name and email. This leaves kwargs like the following:

kwargs = {
    'street': "Street",
    'city': "City",
    'state': "State",
    'code': "0123",
}

Next, AddressHolder.__init__ is called which takes the arguments street, city, state, and code. So kwargs is left as the following:

kwargs = {}

An empty dictionary! So the final call to object.__init__ happens without passing any arguments, which is good because the object constructor does not accept any.

Now, let’s take a look at the second case now. Here, phone is not an explicit parameter of Friend.__init__, so it is passed as a keyword argument inside the dictionary. In all subsequent calls, the flow is exactly as above, except that phone is never taken out of the kwargs dictionary. So with the final call to object.__init__, kwargs will still look like this:

kwargs = {
    'phone': "01234567",
}

And that’s a problem for object.__init__ because it does not accept a phone argument (or any really). So that’s why case two will fail here: Because there’s a remaining keyword argument that gets carried until object.__init__.

like image 138
poke Avatar answered Dec 06 '25 00:12

poke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!