我有两个超类,父亲和母亲,他们将由孩子继承。你知道吗
class Father:
def __init__(self, **kwargs):
self.fathername = kwargs["ffn"] + " " + kwargs["fln"]
self.fatherage = kwargs["fa"]
class Mother:
def __init__(self, **kwargs):
self.mothername = kwargs["mfn"] + " " + kwargs["mln"]
self.motherage = kwargs["ma"]
这个班的孩子继承自父母
class Child(Father, Mother):
def __init__(self, **kwargs):
self.name = kwargs["name"] + " " + kwargs["lastname"]
self.age = kwargs["age"]
如果我分别调用他们的__init__()
,我可以初始化父亲和母亲。你知道吗
Father.__init__(self, **kwargs)
Mother.__init__(self, **kwargs)
但是如何使用super()实现同样的效果呢?如果我像下面这样称呼它,它只初始化父亲而不是母亲(因为父亲是MRO中的下一个)
super().__init__(**kwargs)
下面是被覆盖的__str__()
,以显示分配的内容。你知道吗
def __str__(self):
return \
"Im {}, {} years old".format(self.name, self.age) + "\n" + \
"My dad is {} and he is {} years old".format(self.fathername, self.fatherage) + "\n" + \
"My mom is {} and she is {} years old".format(self.mothername, self.motherage)
familyname = "Simpson"
child = Child(**{"name": "Bart", "lastname": familyname, "age": 15, "ffn": "Hommer", "fln": familyname, "fa": 54, "mfn": "Marggie", "mln": familyname, "ma": 46})
当我尝试打印对象时,它将失败,因为母超类从未初始化(当我在子类中使用__init__()
时)
print(child)
The program raises a runtime error
Traceback (most recent call last):
File "/tmp/pyadv.py", line 225, in <module>
print(child)
File "/tmp/pyadv.py", line 217, in __str__
return "Im {}, {} years old".format(self.name, self.age) + "\n" + "My dad is {} and he is {} years old".format(self.fathername, self.fatherage) + "\n" + "My mom is {} and she is {} years old".format(self.mothername, self.motherage)
AttributeError: 'Child' object has no attribute 'mothername'
那么,如何使用super初始化两个超类呢?你知道吗
编辑:
我试图将super(Father, self).__init__(**kwargs)
和super(Mother, self).__init__(**kwargs)
添加到超类__init__()
方法,但出现以下错误:
Traceback (most recent call last):
File "/tmp/pyadv.py", line 225, in <module>
child = Child(**{"name": "Bart", "lastname": familyname, "age": 15, "ffn": "Hommer", "fln": familyname, "fa": 54, "mfn": "Marggie", "mln": familyname, "ma": 46})
File "/tmp/pyadv.py", line 217, in __init__
super().__init__(**kwargs)
File "/tmp/pyadv.py", line 199, in __init__
super(Father, self).__init__(**kwargs)
File "/tmp/pyadv.py", line 208, in __init__
super(Mother, self).__init__(**kwargs)
TypeError: object.__init__() takes no parameters
我还尝试将super(Father, self).__init__()
和super(Mother, self).__init__()
(在__init__()
内没有参数)添加到超类__init__()
方法中,但出现以下错误:
Traceback (most recent call last):
File "/tmp/pyadv.py", line 225, in <module>
child = Child(**{"name": "Bart", "lastname": familyname, "age": 15, "ffn": "Hommer", "fln": familyname, "fa": 54, "mfn": "Marggie", "mln": familyname, "ma": 46})
File "/tmp/pyadv.py", line 217, in __init__
super().__init__(**kwargs)
File "/tmp/pyadv.py", line 199, in __init__
super(Father, self).__init__()
File "/tmp/pyadv.py", line 206, in __init__
self.mothername = kwargs["mfn"] + " " + kwargs["mln"]
KeyError: 'mfn'
解决方案1: @blkkngt从下面剥离
解决方案2: 根超类,详细的here。你知道吗
class Root:
def __init__(self, **kwargs):
pass
class Father(Root):
def __init__(self, **kwargs):
self.fathername = kwargs["ffn"] + " " + kwargs["fln"]
self.fatherage = kwargs["fa"]
super().__init__(**kwargs)
class Mother(Root):
def __init__(self, **kwargs):
self.mothername = kwargs["mfn"] + " " + kwargs["mln"]
self.motherage = kwargs["ma"]
super().__init__(**kwargs)
class Child(Father, Mother):
def __init__(self, **kwargs):
self.name = kwargs["name"] + " " + kwargs["lastname"]
self.age = kwargs["age"]
super().__init__(**kwargs)
def __str__(self):
return \
"Im {}, {} years old".format(self.name, self.age) + "\n" + \
"My dad is {} and he is {} years old".format(self.fathername, self.fatherage) + "\n" + \
"My mom is {} and she is {} years old".format(self.mothername, self.motherage)
familyname = "Simpson"
child = Child(**{"name": "Bart", "lastname": familyname, "age": 15, "ffn": "Homer", "fln": familyname, "fa": 54, "mfn": "Marge", "mln": familyname, "ma": 46})
print(child)
Python中的多重继承需要协作。也就是说,两个父类需要知道彼此存在的可能性(尽管它们不需要知道彼此的任何细节)。然后,无论哪个父级先被命名,都可以调用另一个父级的
__init__
方法。这就是super
的工作方式,它总是调用被操作实例的MRO(方法解析顺序)中的下一个类。你知道吗您的代码很难正确执行此操作,因为您总是在
super
调用中传递完整的kwargs
dict。当第二个父级试图调用MRO中的最后一个类object
时,这就成了一个问题,这个类不希望接收任何关键字参数。相反,每个类的__init__
方法通常应该显式地命名它所期望的参数,并且在调用super().__init__
时不要再次传递这些参数(除非它知道它的一个父类也需要参数)。你知道吗试试这个:
请注意,在python3中,通常不需要向
super()
传递任何参数,它可以确定从哪个类调用它并自动工作。在Python2中,您必须指定当前类,但这不再需要了。你知道吗最后一个音符。虽然我确信你的代码只是一个例子,但在面向对象设计方面,类的名称是非常糟糕的。继承意味着这两个类之间存在一种IS-A关系,这实际上并不适合人。例如,在示例代码(Bart)中创建的子级不是
Mother
或Father
,但是代码说他是,因为他是Mother
和Father
类的实例。描述与父母之间人际关系的更好方法是HAS-A。每个孩子都有一个母亲和一个父亲。您可以使用封装来建立HAS-A关系。这意味着,子对象对属性中每个父对象都有一个引用。有趣的是,只需一节课就可以做到这一点(这可能就是为什么你没有学习这一点,如果你被教导继承的话):根据本link中的公认答案:
相关问题 更多 >
编程相关推荐