[toc]
1、重写
在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个特点我们成为叫做方法的重写(覆盖:
override
)。
故事继续:徒弟掌握了师父和学院派技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。
# 1.创建师父类,属性和方法class Master(object):def __init__(self):self.kongfu = \'[古法煎饼果子配方]\'def make_cake(self):print(f\'运用{self.kongfu}制作煎饼果子\')# 2.创建学院派类 属性和方法class School(object):def __init__(self):self.kongfu = \'[学院派煎饼果子配方]\'def make_cake(self):print(f\'运用{self.kongfu}制作煎饼果子\')# 3.独创配方class Prentice(School, Master):def __init__(self):self.kongfu = \'[独创煎饼果子配方]\'def make_cake(self):print(f\'运用{self.kongfu}制作煎饼果子\')# 4. 用徒弟类创建对象,调用实例属性和方法tudi = Prentice()print(tudi.kongfu)tudi.make_cake()"""输出结果[独创煎饼果子配方]运用[独创煎饼果子配方]制作煎饼果子"""
结论:子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
拓展:
当我们调用一个对象的方法时,会优先去当前对象中寻找是否具有该方法,如果有则直接调用。
如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法。
如果没有,则去父类的父类中寻找,以此类推,直到找到object,如果依然没有找到,则报错。
2、super()函数
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用
super()
函数来实现。
实际需求就是:子类调用父类的同名方法和属性。
方式一
故事继续:虽然自己独创的煎饼果子配方非常受欢迎,但是还是有顾客都希望也能吃到古法和学院技术的煎饼果子。
# 1.创建师父类,属性和方法class Master(object):def __init__(self):self.kongfu = \'[古法煎饼果子配方]\'def make_cake(self):print(f\'运用{self.kongfu}制作煎饼果子\')# 2. 定义徒弟类,继承师父类# 添加和父类同名的属性和方法class Prentice(Master):def __init__(self):self.kongfu = \'[独创煎饼果子配方]\'# 子类的make_cake(self)方法def make_cake(self):"""加自己的初始化的原因:如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,如果不加这个自己的初始化,kongfu属性值是上一次调用的init内的kongfu属性值执行方式如下:# 创建一个子类对象tudi = Prentice()# 调用执行父类中的make_cake()方法tudi.make_master_cake()# 调用子类中的make_cake()tudi.make_cake()就能看到劫、结果。所以在调用属性前,先调用自己子类的初始化,要记住。"""self.__init__()print(f\'运用{self.kongfu}制作煎饼果子\')# 调用父类的make_cake()方法# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化def make_master_cake(self):# 父类类名.函数()# 再次调用初始化的原因:这里想要调用父类的同名方法和属性,# 属性在init初始化位置,所以需要再次调用initMaster.__init__(self)Master.make_cake(self)# 3 . 用徒弟类创建对象,调用实例属性和方法# 创建一个子类对象tudi = Prentice()# 调用执行父类中的make_cake()方法tudi.make_master_cake()# 调用子类中的make_cake()tudi.make_cake()"""输出结果:运用[古法煎饼果子配方]制作煎饼果子运用[独创煎饼果子配方]制作煎饼果子"""
方式一:
make_master_cake()
方法中的代码冗余;父类类名如果变化,那么在子类中会涉及多处修改,另外,Python是允许多继承的语言,如上所示的方法在多继承时就需要重复写多次,显得累赘。为了解决这些问题,Python提供了
super()
函数解决此问题。
方式二
使用
super()
函数调用父类中的同名方法。
# 1.创建师父类,属性和方法class Master(object):def __init__(self):self.kongfu = \'[古法煎饼果子配方]\'def make_cake(self):print(f\'运用{self.kongfu}制作煎饼果子\')# 2. 定义徒弟类,继承师父类# 添加和父类同名的属性和方法class Prentice(Master):def __init__(self):self.kongfu = \'[独创煎饼果子配方]\'# 子类的make_cake(self)方法def make_cake(self):self.__init__()print(f\'运用{self.kongfu}制作煎饼果子\')# 调用父类的make_cake()方法# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化def make_master_cake(self):# 方法二: super()# super函数需要传递的参数:(当前类名, self)前边是类名,后边是对象# 方式一: super(当前类名, self).函数()# super(Prentice, self).__init__()# super(Prentice, self).make_cake()# 方式二; 简便方法,使用super().函数(),参数可省略。super().__init__()super().make_cake()# 3 . 用徒弟类创建对象,调用实例属性和方法# 创建一个子类对象tudi = Prentice()# 调用执行父类中的make_cake()方法tudi.make_master_cake()# 调用子类中的make_cake()tudi.make_cake()"""输出结果:运用[古法煎饼果子配方]制作煎饼果子运用[独创煎饼果子配方]制作煎饼果子"""
注意:使用
super()
函数可以自动查找父类。调用顺序遵循
__mro__
类属性的顺序。比较适合单继承使用。
__mro__
内置类属性说明
在Python中快速查看一个类的所继承的父类,以及父类的层级关系的方法,返回的结果是一个元组。
# 如上边示例# 语法:类名.__mro__print(Prentice.__mro__)"""输出结果:(<class \'__main__.Prentice\'>, <class \'__main__.Master\'>, <class \'object\'>)可以看到返回的是一个元组,`super()`函数在这个元组的类中,依次查找相关属性或方法。"""