Python3 Multiple inheritance TypeError: object.__init__() takes no parameters
Python3 Multiple inheritance TypeError: object.__init__() takes no parameters
我正在 Python3 中学习多重继承。我想知道为什么 case#1 有效而 case#2 无效。这是我的代码片段。
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="myfriend@example.net",
street="Street",
city="City",
state="State",
code="0123")
这是脚本的输出。如果我在 "Friend" 中仅使用 kwargs(案例 # 2)作为继承 "Contact" 和 "AddressHolder" 的参数,那么 Python 会出错。我已经测试了没有继承的相同类型的构造,除了对象,它工作得很好。
"""
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
>>>
"""
我们来看看Friend
的方法解析顺序。这将告诉我们构造函数的调用顺序:
>>> Friend.mro()
[<class '__main__.Friend'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>]
那么我们先来看案例1。这些是 Friend
构造函数的原始命名参数:
phone="01234567"
name="My Friend"
email="myfriend@example.net"
street="Street"
city="City"
state="State"
code="0123"
现在,Friend.__init__
将 phone
作为显式参数,然后将其余部分作为关键字参数字典。所以 kwargs
如下:
kwargs = {
'name': "My Friend",
'email': "myfriend@example.net",
'street': "Street",
'city': "City",
'state': "State",
'code': "0123",
}
接下来,调用 Contact.__init__
,它接受参数 name
和 email
。这使得 kwargs
如下所示:
kwargs = {
'street': "Street",
'city': "City",
'state': "State",
'code': "0123",
}
接下来,调用 AddressHolder.__init__
,它接受参数 street
、city
、state
和 code
。所以kwargs
就剩下如下:
kwargs = {}
一本空字典!所以对 object.__init__
的最终调用没有传递任何参数,这很好,因为 object
构造函数不接受任何参数。
现在我们来看第二个案例。这里,phone
不是 Friend.__init__
的显式参数,因此它在字典中作为关键字参数传递。在所有后续调用中,流程与上面完全相同,只是 phone
永远不会从 kwargs
字典中取出。所以最后一次调用 object.__init__
,kwargs
仍然是这样的:
kwargs = {
'phone': "01234567",
}
这对 object.__init__
来说是个问题,因为它不接受 phone
参数(或任何真正的参数)。所以这就是案例二在这里失败的原因:因为还有一个剩余的关键字参数被携带直到 object.__init__
.
我正在 Python3 中学习多重继承。我想知道为什么 case#1 有效而 case#2 无效。这是我的代码片段。
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="myfriend@example.net",
street="Street",
city="City",
state="State",
code="0123")
这是脚本的输出。如果我在 "Friend" 中仅使用 kwargs(案例 # 2)作为继承 "Contact" 和 "AddressHolder" 的参数,那么 Python 会出错。我已经测试了没有继承的相同类型的构造,除了对象,它工作得很好。
"""
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
>>>
"""
我们来看看Friend
的方法解析顺序。这将告诉我们构造函数的调用顺序:
>>> Friend.mro()
[<class '__main__.Friend'>, <class '__main__.Contact'>, <class '__main__.AddressHolder'>, <class 'object'>]
那么我们先来看案例1。这些是 Friend
构造函数的原始命名参数:
phone="01234567"
name="My Friend"
email="myfriend@example.net"
street="Street"
city="City"
state="State"
code="0123"
现在,Friend.__init__
将 phone
作为显式参数,然后将其余部分作为关键字参数字典。所以 kwargs
如下:
kwargs = {
'name': "My Friend",
'email': "myfriend@example.net",
'street': "Street",
'city': "City",
'state': "State",
'code': "0123",
}
接下来,调用 Contact.__init__
,它接受参数 name
和 email
。这使得 kwargs
如下所示:
kwargs = {
'street': "Street",
'city': "City",
'state': "State",
'code': "0123",
}
接下来,调用 AddressHolder.__init__
,它接受参数 street
、city
、state
和 code
。所以kwargs
就剩下如下:
kwargs = {}
一本空字典!所以对 object.__init__
的最终调用没有传递任何参数,这很好,因为 object
构造函数不接受任何参数。
现在我们来看第二个案例。这里,phone
不是 Friend.__init__
的显式参数,因此它在字典中作为关键字参数传递。在所有后续调用中,流程与上面完全相同,只是 phone
永远不会从 kwargs
字典中取出。所以最后一次调用 object.__init__
,kwargs
仍然是这样的:
kwargs = {
'phone': "01234567",
}
这对 object.__init__
来说是个问题,因为它不接受 phone
参数(或任何真正的参数)。所以这就是案例二在这里失败的原因:因为还有一个剩余的关键字参数被携带直到 object.__init__
.