《手把手陪您学Python》43——类的继承

在上一篇《手把手陪您学Python》42——类的魔法方法中,我们学习了如何通过实例方法去定义实例属性,并且对__init__()方法的应用进行了介绍。

​今天,我们将会继续深入学习面向对象编程,介绍类的继承和魔法方法在其中的应用。

我们之前学习的类的实例化,是指将类具体到某一特定的事物的过程,这个事物就是类的实例,他具有类的全部属性和方法。

类的继承实际上也具有原来类的全部属性和方法,只不过他不是从原来类具体化成的某一特定事物,而是在原来类的基础上派生出来的新的类。他既具有原来类的全部属性和方法,同时还可以有只属于自己的属性和方法,更重要的是,因为他是一个类,所以还可以再实例化。

继承出来的类和原来的类是继承或者说派生的关系,原来的类称之为“父类”,继承出来的新类称之为“子类”。

1、子类的创建

在创建子类时,父类必须同时包含在当前文件中,而且要位于子类的前面。

定义继承类的方法与定义类的方法近似,也是使用class关键字,也包括“:”和缩进的格式要求,只不过在继承类名称的后面要在括号里指定父类的名称,以告诉Python他们之间的“父子”关系,这时新的“子类”才能够继承“父类”的属性和方法。

class 子类名称(父类名称):
    语句1
    语句2
    。。。

下面,让我们继续请出马里奥先生,给我们展示类的继承的使用和效果。

我们可以将吃了“花”之后的马里奥设置为马里奥类的继承类,名字就叫做超级马里奥吧。虽然他具有马里奥类的一些属性和方法,但还有自己独特的属性和方法,比如帽子变成了白色,攻击方式也可以发射子弹了。

这种在子类中定义与父类不同的属性或者方法称之为“重写”或者“覆盖”。

In [1]: class Mario:   # 先定义马里奥类
            life = 3
            cap = "red"
            def jump(self):
                print("Mario is jumping!")
            def attack(self,name):
                print("Mario attacked an anomy!")
In [2]: class Super_Mario(Mario):   # 定义马里奥类的继承类
            cap = "write"   # 只需要定义不同的属性
            def attack(self,name):   # 只需要定义不同的方法
                print("{} shot a bullet!".format(name))
In [3]: print(Super_Mario.life)   # 继承父类的属性
        print(Super_Mario.cap)   # 重写父类的属性
        Super_Mario.jump()   # 由于在子类中定义的是实例方法,所以类的方法会报错
out[3]: 3
        write
        ---------------------------------------------------------------------------
        TypeError                                 Traceback (most recent call last)
        <ipython-input-14-d262ae1d363e> in <module>
              1 print(Super_Mario.life)   # 继承父类的属性
              2 print(Super_Mario.cap)   # 重写父类的属性
        ----> 3 Super_Mario.jump()   # 由于在子类中定义的是实例方法,所以类的方法会报错
​
        TypeError: jump() missing 1 required positional argument: 'self'
In [4]: Super_big_Mario = Super_Mario()   # 子类的实例化
        Super_big_Mario.size = "big"   # 定义实例属性
In [5]: print(Super_big_Mario.life)   # 引用类属性
        print(Super_big_Mario.cap)   # 引用类属性
        print(Super_big_Mario.size)   # 引用实例属性
        Super_big_Mario.jump()   # 引用实例方法
        Super_big_Mario.attack("Super big Mario")   # 引用实例方法
Out[5]: 3
        write
        big
        Mario is jumping!
        Super big Mario shot a bullet!

在上面的程序中,我们验证了:

1、通过定义类以及继承类,子类可以继承父类的属性和方法,同时子类还可以定义自己的类属性和实例方法;

2、子类实例化后,可以引用没有被子类覆盖的父类的属性和方法,也可以引用子类自己的类属性和实例方法,还可以定义自己的实例属性。

如果我们能够数量掌握之前学习过的语法规则和概念,理解上面继承类的语法规则和程序应该是比较容易的。只需要区分哪些是父类的属性和方法,哪些是子类覆盖父类的属性和方法,然后在引用时加以区分就可以了。

2、子类的魔法方法

上面我们通过最基本的方式创建了父类、子类的继承关系,并验证了一系列的属性和方法。接下来,我们将在子类中引用上一篇学习的魔法方法,看看又会有哪些神奇的效果。

In [6]: class Mario:   # 先定义父类马里奥
            def __init__(self, life, cap, name, food):   # 保留之前使用的四个参数
                self.life = life
                self.cap = cap
                print("{} has {} lifes.".format(name, self.life))
                print("{} has a {} cap.".format(name, self.cap))
                self.jump()
                self.eat(name, food)
                self.attack(name)
            def jump(self):
                print("Mario is jumping!")
            def attack(self,name):
                print("{} attacked an anomy!".format(name))
            def eat(self, name, food):
                print("Mario ate a {}!".format(food))
                print("{} became bigger!".format(name))
In [7]: class Super_Mario(Mario):
            def __init__(self, life, cap, name, food):   # 初始化父类的属性
                super().__init__(life, cap, name, food)   # super()用来调用父类的方法
In [8]: Super_big_Mario = Super_Mario(30, "White", "Super Mario", "red mushroom")  # 定义子类实例
Out[8]: Super Mario has 30 lifes.
        Super Mario has a White cap.
        Mario is jumping!
        Mario ate a red mushroom!
        Super Mario became bigger!
        Super Mario attacked an anomy!

虽然在上面的代码中加入了部分注释,但可能看起来还是会有些不知所云,那么就让我们一点一点来解释。

首先,定义父类的代码应该没有什么问题,和我们上一篇介绍魔方方法时的代码是一样的。

其次,在定义子类时,只有一个方法,而且是一个__init__()方法。根据我们之前学习的内容,在定义子类实例的时候,__init__()方法将会自动执行,__init__()方法中的参数将在定义子类实例的同时被定义。

最后,非常神奇的一点是super()函数的应用,他让子类能够调用父类的方法,也就是说super().__init__(life, cap, name, food)这样一行代码所起到的作用,是调用父类的__init__()方法,而父类__init__()方法的参数又来自于子类__init__()方法的参数,也就是在定义子类实例的同时定义了父类的属性!

这里,我们又一次体验了魔法方法的神奇之处。子类实例不仅能够定义子类的属性,还能够同时定义父类属性!

以上就是对类的继承的介绍,除了__init__()方法中的一些内容外,都是我们在介绍类的概念时都学习过的内容,这里一方面介绍了类的继承以及子类的创建,同时也对之前学习的内容进行了总结。

下一篇,我们将会介绍面向对象的最后一部分内容——类的导入,敬请关注。

 

图片

 


感谢阅读本文!如有任何问题,欢迎留言,一起交流讨论^_^

要阅读《手把手陪您学Python》系列文章的其他篇目,请关注公众号点击菜单选择,或点击下方链接直达。

《手把手陪您学Python》1——为什么要学Python?

《手把手陪您学Python》2——Python的安装

《手把手陪您学Python》3——PyCharm的安装和配置

《手把手陪您学Python》4——Hello World!

《手把手陪您学Python》5——Jupyter Notebook

《手把手陪您学Python》6——字符串的标识

《手把手陪您学Python》7——字符串的索引

《手把手陪您学Python》8——字符串的切片

《手把手陪您学Python》9——字符串的运算

《手把手陪您学Python》10——字符串的函数

《手把手陪您学Python》11——字符串的格式化输出

《手把手陪您学Python》12——数字

《手把手陪您学Python》13——运算

《手把手陪您学Python》14——交互式输入

《手把手陪您学Python》15——判断语句if

《手把手陪您学Python》16——循环语句while

《手把手陪您学Python》17——循环的终止

《手把手陪您学Python》18——循环语句for

《手把手陪您学Python》19——第一阶段小结

《手把手陪您学Python》20——列表

《手把手陪您学Python》21——元组

《手把手陪您学Python》22——字典

《手把手陪您学Python》23——内置序列函数

《手把手陪您学Python》24——集合

《手把手陪您学Python》25——列表推导式

《手把手陪您学Python》26——自定义函数

《手把手陪您学Python》27——自定义函数的参数

《手把手陪您学Python》28——自定义函数的返回值

《手把手陪您学Python》29——匿名函数

《手把手陪您学Python》30——模块

《手把手陪您学Python》31——文件的打开

《手把手陪您学Python》32——文件的读取

《手把手陪您学Python》33——文件的关闭

《手把手陪您学Python》34——文件的写入

《手把手陪您学Python》35——数据的存储

《手把手陪您学Python》36——错误和异常处理

《手把手陪您学Python》37——程序的重构

《手把手陪您学Python》38——第二阶段小结

《手把手陪您学Python》39——面向对象

《手把手陪您学Python》40——类的定义、属性与实例化

《手把手陪您学Python》41——类的方法与实例方法

《手把手陪您学Python》42——类的魔法方法

For Fans:关注“亦说Python”公众号,回复“手43”,即可免费下载本篇文章所用示例语句。

亦说Python——Python爱好者的学习分享园地
 
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值