关于python:使用__init__继承属性

The inheritance of attributes using __init__

我是刚开始学习Python的Java人。举个例子:

1
2
3
4
5
6
7
8
9
10
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中,上面的代码有很多冗余)。

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


在python中为类编写__init__函数时,应始终调用其超类的__init__函数。我们可以使用它将相关属性直接传递给超类,因此您的代码如下所示:

1
2
3
4
5
6
7
8
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

正如其他人指出的那样,你可以替换这条线

1
Person.__init__(self, name, phone)

具有

1
super(Teenager, self).__init__(name, phone)

代码也会做同样的事情。这是因为在python中,instance.method(args)只是Class.method(instance, args)的简写。如果您想使用super,您需要确保指定object作为Person的基类,正如我在代码中所做的那样。

python文档提供了有关如何使用super关键字的更多信息。在这种情况下,重要的是它告诉python在self的超类中查找方法__init__,而不是Teenager


稍微干净一点,我喜欢这样做:

1
2
3
4
class Teenager(Person):
        def __init__(self, *args, **kwargs):
           self.website=kwargs.pop('website')
           super(Teenager, self).__init__(*args, **kwargs)

在这种情况下,这并没有多大的区别,但是当你有一个__init__和大量的争论时,它会让生活变得更容易。


如果在构造函数中定义了python中的属性,并且不调用父类构造函数,则不会继承这些属性,除非手动执行所有操作:

1
2
3
4
5
6
7
8
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继承


到目前为止,所有的例子都是针对python 2.x的,但是这里有一个针对python 3.x的解决方案,它使用了较短的super()版本,并且不从对象继承。

1
2
3
4
5
6
7
8
9
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


与Java构造函数不同,EDCOX1×0是不为继承层次结构中的每个类自动调用的,您需要自己完成。

此外,所有对象层次结构都应该在object上建立根(特殊情况除外)。

您的代码应为:

1
2
3
4
5
6
7
8
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的委托对象,而不是直接调用一个超类构造函数。