Python子类初始化器

4
在Python面向对象编程中,假设Person是一个父类,有自己的初始化器;那么Student是Person的子类,在使用Student之前,必须在Student的初始化器中首先调用Person.__init__(self)吗?此外,我能否在Student类中定义一个新的初始化器?
class Person():      
    def __init__(self):  

上面是类Person及其初始化器。
class Student(Person):    
    def __init__(self):  
        Person.__init__(self)   
    def __init__(self, age)

我的意思是,学生类是否可以有自己的初始化函数?如果可以,那么在学生类的初始化函数中必须调用Person.__init__(self)吗?
6个回答

9
当然,Student 可以有自己的初始化方法。然而,在 Python 中,一个类只能有一个初始化方法,因为这是在构造函数中调用的特殊方法(即类的 __new__ 方法)。
因此,当我们说子类有自己的初始化方法时,实际上指的是像这样的情况:
class Worker(People):
    def __init__(self, company):
        self.company = company

正如 @IanH 指出的那样,您不必调用超类初始化程序。当您认为应该调用它时(可能是为了进行一些常见的初始化),可以像这样执行:
class People:
    def __init__(self, name):
        self.name = name

class Student(People):
    def __init__(self, name, school):
        super(Student, self).__init__(name)
        self.school = school

那可能很棒,我关心的是所谓的“构造函数重载”,现在我正在路上。 - ladyfafa
1
这是正确的方法,但是在这里了解更多关于super()的真正作用:http://fuhm.net/super-harmful/。从更一般的意义上讲,使用**kwargs和关键字参数的重点在于在许多情况下都很有用。 - clacke
谢谢分享链接。但如果我正确理解了这篇文章,那么只有在尝试使用多重继承时它才是有害的,对吗?所以我认为是多重继承有害 :) - satoru

4
不,它看起来应该是这样的:

class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weigth = weight


class Student(Person):
    def __init__(self, name, age, height, weight, school):
        Person.__init__(self, name, age, heigth, weight)
        self.school = school

如果在Student类中没有Person.__init__,那么如果你想把它像一个人一样使用,你就需要在Student类中做所有在Person类中所做的事情。

@sth,顺便问一下,我该如何在此处发布代码时将其编辑成漂亮的格式?你的代码看起来很好。 - ladyfafa
ladyfafa:只需将代码行缩进4个空格(加上Python代码的空格),Stackoverflow就会自动着色。 - IanH
另外,你应该使用 super - habnabit
@ Aaron Gallapher,你可以这样做,但我发现它会导致更多的混淆,而面向对象编程本身已经很令人困惑了。 - Zimm3r
关于 super() 有一些注意事项,请阅读:http://fuhm.net/super-harmful/ - clacke
显示剩余3条评论

1

不一定非要这样做,但最好还是这么做。如果基类有任何未在派生类中重写的方法或属性,则应调用基类的初始化程序,否则这些方法和属性可能无法正常工作。

编辑:让我澄清一下。您可以为Student定义一个初始化程序,但该初始化程序确实应调用Person.__init__以确保正确初始化基类。


1

Student 可以有自己的初始化器。在 Python 中,您可以选择调用或不调用基类的初始化器,但最好的做法是这样做。


0

改编自Zimm3r的答案,但使用super以达到最大的正确性:

class Person(object):
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weigth = weight


class Student(Person):
    def __init__(self, name, age, height, weight, school):
        super(Student, self).__init__(name, age, heigth, weight)
        self.school = school

0
你可以重载Python的__new__,它位于__init__之前,这就是你在原始问题中寻找的东西。
def __new__(cls, *args, **kwargs):pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接