使用__init__继承属性

时间:2012-01-13 16:37:04

标签: python inheritance attributes polymorphism

我是刚开始学习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中,上面的代码有很多冗余)。

关于哪些属性已从父类继承,哪些部分是多余的?

5 个答案:

答案 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)

与java构造函数不同,

__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的委托对象而不是直接调用超类构造函数这一事实的一个实际结果。