我是刚开始学习Python的Java人。举个例子:
class Person():
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def __init__(self, name, phone, website):
self.name=name
self.phone=phone
self.website=website
我确信有很多冗余代码(我知道在Java中,上面的代码有很多冗余)。
关于哪些属性已从父类继承,哪些部分是多余的?
答案 0 :(得分:42)
在python中为类编写__init__
函数时,应始终调用其超类的__init__
函数。我们可以使用它将相关属性直接传递给超类,因此您的代码将如下所示:
class Person(object):
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def __init__(self, name, phone, website):
Person.__init__(self, name, phone)
self.website=website
正如其他人所指出的那样,你可以替换
行Person.__init__(self, name, phone)
与
super(Teenager, self).__init__(name, phone)
代码将执行相同的操作。这是因为在python中instance.method(args)
只是Class.method(instance, args)
的简写。如果您想使用super
,则需要确保将object
指定为Person
的基类,就像我在代码中所做的那样。
python documentation提供了有关如何使用super
关键字的更多信息。在这种情况下,重要的是它告诉python在__init__
的超类self
Teenager
答案 1 :(得分:13)
我喜欢这样做的方式更清洁:
class Teenager(Person):
def __init__(self, *args, **kwargs):
self.website=kwargs.pop('website')
super(Teenager, self).__init__(*args, **kwargs)
在这种情况下,它没有太大的区别,但是如果你有一个__init__
有大量的参数,它会让生活更轻松。
答案 2 :(得分:6)
当在构造函数中定义并且未调用父类构造函数时,Python中的属性不会被继承,除非您手动完成所有这些属性:
class Person():
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def_init_(self, name, phone, website):
Person.__init__(self, name, phone) # Call parent class constructor.
self.website=website
更多相关信息:http://docs.python.org/tutorial/classes.html#inheritance
答案 3 :(得分:5)
到目前为止,所有的例子都是针对Python 2.x的,但是这里是Python 3.x的一个解决方案,它使用了较短版本的super()并且不从对象继承。
class Person:
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def __init__(self, name, phone, website):
super().__init__(name, phone)
self.website = website
答案 4 :(得分:1)
__init__
不会为继承层次结构中的每个类自动调用 - 您需要自己执行此操作。
此外,所有对象层次结构都应以object
为根(除特殊情况外)。
您的代码应为:
class Person(object):
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Teenager(Person):
def_init_(self, name, phone, website):
super(Teenager, self).__init__(name, phone)
self.website=website
super
为其第二个参数(self
)创建一个委托,它将调用函数列表中的下一个函数来调用每个名称(“方法解析顺序”)。这与调用超类方法并不完全相同,就像在Java中发生的那样。
您也可以编写super(type(self), self).__init__(name, phone)
,但如果您继承此类,type(self)
可能不是Teenager
,您可以进行无限递归。这是因为您使用具有差异MRO的委托对象而不是直接调用超类构造函数这一事实的一个实际结果。