相关推荐recommended
Python类的继承
作者:mmseoamin日期:2023-12-19

一、类的继承

众所周知,Python是面向对象编程。而面向对象编程主要好处之一便是代码的重用。Python实现代码重用的方法之一是通过继承。

继承是类和类之间的一种关系,是一种子类和父类的关系。如子类继承父类,而Python类中重要的两个东西便是属性和方法。那么Python的子类是如何继承父类的属性和方法?是选择性继承还是不可更改?下面我们将一一展开说明。Python中有单继承和多继承,单继承即子类继承于一个父类,多继承即子类继承多个类。本文主要介绍常见的单继承。

a.继承父类的方法

首先,我们先看一段代码例子。

class Foo:
    def f1(self):
        print('Foo.f1')
    def f2(self):
        print('Foo.f2')
        self.f1()
class H(Foo): # 继承父类Foo
    pass
h = H()
h.f1() # Foo.f1
class Bar(Foo): # 继承父类Foo
    def f1(self):
        print('Bar.f1')
b = Bar()
b.f1() # Bar.f1

这个代码就生动的展示了子类如何继承父类的方法。通常情况下当有了继承关系,子类在查找方法时,先从自己的本身类中寻找方法,如果找到了,就直接调用(如代码中的Bar类);如果找不到该方法就到父类寻找该方法(如代码中的H)。也可以这样理解,当有了继承关系后,子类就直接把父类的方法复制下来了,子类可以重写父类的方法。

既然子类可以重新写父类的方法,那么父类有没有一种方法能够不让子类覆盖自己的方法。Python中提供了双下划线开头的方式将方法设置为私有。

Python类的继承,在这里插入图片描述,第1张

下面,看一个有意思的例子。我们知道了子类先在自身找方法f2,找不到了再去父类找方法f2。但如果出现了找到的父类方法f2中调用了被子类重写的方法f1,这时是调用父类本身的方法f1还是子类的方法f1呢(有点绕,看下面的代码就容易理解了)。答案是调用子类重写的方法f1。

其实比较有意思的是如果把父类中的方法f1注释掉,即下面代码中Foo类的f1函数注释掉,下面代码运行结果还是和未注释是一样的。

class Foo:
    def f1(self):
        print('Foo.f1')
    def f2(self):
        print('Foo.f2')
        self.f1()
class Bar(Foo):
    def f1(self):
        print('Bar.f1')
b = Bar()
b.f2() # Foo.f2, Bar.f1
class Foo:
    def f2(self):
        print('Foo.f2')
        self.f1()
class Bar(Foo):
    def f1(self):
        print('Bar.f1')
b = Bar()
b.f2() # Foo.f2, Bar.f1

好了,如果上述代码的父类Foo中的f1变成私有方法了。那么,这时子类Bar能不能重写f1呢。答案是不能的(加了双下划线的方法是不能从外部调用的)。

class Foo:
    def __f1(self):
        print('Foo.f1')
    def f2(self):
        print('Foo.f2')
        self.__f1()
class Bar(Foo):
    def __f1(self):
        print('Bar.f1')
b = Bar()
b.f2() # Foo.f2, Foo.f1
b.__f1() # 报错

b.继承父类的属性

上述代码中的类都没有写属性。那么子类继承父类的属性是啥都不用写就可以直接使用吗?答案是是的。

Python类的继承,在这里插入图片描述,第2张

那么,如果子类重写了 __init__ 时,就不会调用父类已经定义的 __init__ 。

Python类的继承,在这里插入图片描述,第3张

那么有一种情况就是子类想要继承父类的属性(也就是父类的__init__该咋办呢)。可以使用super关键字:

Python类的继承,在这里插入图片描述,第4张

这里是直接把父类的整个__init__都搬过来了。