前言
系列文章目录
[Python]目录
视频及资料和课件
链接:https://pan.baidu.com/s/1LCv_qyWslwB-MYw56fjbDg?pwd=1234
提取码:1234
视频链接
根据视频进行整理
Python继承
目标
- 继承的概念
- 单继承
- 多继承
- 子类重写父类的同名属性和方法
- 子类调用父类的同名属性和方法
- 多层继承
- super()
- 私有属性和私有方法
1 继承
1.1 继承的概念
在日常生活中,继承,即子代继承父代的财产。
在面向对象编程中,继承,即子类继承父类的属性与方法。
因此,即使子类中没有任何属性与方法,只要继承了父类,就可以拥有父类的属性与方法。
继承的作用:可以简化代码。
1.2 (拓展)经典类和新式类
在python中,不同版本的解释器下,类默认有两种执行方式,一种按照经典类执行,一种按照新式类执行。
现在,使用的python解释器版本基本为3.0。
在python2.0版本的解释器下,类的执行默认按照经典类的方式执行:
class 类名:
代码
......
在python3.0版本的解释器下,类的执行默认按照新式类的方式执行:
一个类如果没有继承其他类,会默认继承一个所有类的顶级类,object。
没有写继承的类,在括号中无论是否有写object,都会默认继承object。
object,也称为基类。
class 类名(object):
代码
......
在以后书写类的代码,一般都写成新式类的形式。
类名后面的括号中写要继承的类。
1.3 体验继承
Python面向对象的继承指的是多个类之间的所属关系,即子类默认基础父类的所有属性和方法。
继承的作用:简化代码的书写。
不同的类拥有相同的属性和方法,可以使用继承来简化代码的书写。
在Python中,所有类默认继承object类,object类是顶级类或基类,其他的类叫做派生类。
由于object类之外的其他类,要么继承其他类,要么默认继承object类,即其他类都派生于某个类,所以object类之外的其他类叫做派生类。
# 父类
# 也可以写成:class A():
# 因为没有指定继承的类,会默认继承object类
class A(object):
def __init__(self):
self.num = 1
def print_info(self):
print(self.num)
# 子类
class B(A):
pass
b = B()
b.print_info()
由于B继承A,所以B会拥有A的所有方法,在实例化B类的对象b时,会自动调用从A类继承过来的
__init__()
方法,初始化实例的对象b。
由于继承了所有方法,实例化的对象b也可以调用print_info()
方法。
2 单继承
单继承,即一个父类被一个子类继承,一个子类继承一个父类。
场景:一位老师傅要将其煎饼果子的配方传授给其徒弟。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 徒弟类
class Prentice(Master):
pass
# 实例化徒弟对象
prentice = Prentice()
# 徒弟使用从师傅那继承的配方制作煎饼果子
prentice.make_cake()
3 多继承
假设上述例子中徒弟的姓名为大邱,大邱在继承煎饼果子配方后,还想学习编程技术,于是报班学习编程技术。
于是,大邱不仅从师傅那继承了煎饼果子的配方,还从培训班那学习到了编程技术。
多继承,即一个类同时继承多个父类。
注意:
当一个类有多个父类的时候,默认使用第一个
父类的同名属性和方法。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(object):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 徒弟类
class Prentice(School, Master):
pass
# 实例化徒弟对象
prentice = Prentice()
# 制作煎饼果子
prentice.make_cake()
4 子类重写父类同名方法和属性
4.1 子类重写父类同名方法和属性
子类与父类有同名的方法和属性,子类的对象调用同名方法和属性,调用的是子类的方法和属性。
大邱在继承了师傅的煎饼果子配方,以及在培训机构学习了编程技术后,经过自己的研究,最终研究出了自己的一套制作煎饼果子的方法与技术。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(object):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 徒弟类
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
# 实例化徒弟对象
prentice = Prentice()
# 制作煎饼果子
prentice.make_cake()
4.2 查看子类继承的父类以及父类间的层级关系
语法:
需要查看的类的类名.__mro__
print(Prentice.__mro__)
Prentice直接继承于School与Master,间接继承于object。
5 子类调用父类的同名方法和属性
5.1 子类调用父类的同名方法和属性
虽然现在有了大邱研究出的新型制作煎饼果子的方法与技术,但是顾客们还是非常怀念古法煎饼果子,顾客询问大邱,能不能制作古法煎饼果子。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(object):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 徒弟类
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
# 古法煎饼果子制作
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
# 实例化徒弟对象
prentice = Prentice()
# 制作煎饼果子
prentice.make_cake()
prentice.make_master_cake()
5.2 解释
调用父类初始化方法的原因,使用父类初始化方法重置子类对象的属性,如果不调用,子类对象的属性不会更改。
由于调用父类的初始化方法后,子类对象的属性会被修改,所以使用子类自己的属性时候,需要调用子类的初始化方法重置属性值。
6 多层继承
n年之后,大邱老了,想把自己的技术与配方传承给自己的徒弟。
大邱继承了培训机构与其师傅的技术和配方,大邱的徒弟继承了大邱的技术与配方,这就是多层继承的体现。
类名调用父类的方法,注意传递形参self。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(object):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 徒弟类
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
# 古法煎饼果子制作
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
# 徒孙类
class TuSun(Prentice):
pass
# 实例化徒弟对象
xiaoqiu = TuSun()
# 制作煎饼果子
# 使用从其师傅(大邱)继承的方法与配方制作
xiaoqiu.make_cake()
xiaoqiu.make_master_cake()
7 super()
调用父类的方法
调用父类的方法:
(1)可以通过父类的类名调用
(2)也可以通过super()调用
Master、School、Prentice三个类的继承关系改为,School继承Master,Prentice继承School。
7.1 通过父类的类名调用
使用类名调用父类方法的形式,一次性调用父类School、Master的方法。
此方法存在的缺陷:
当父类的类名修改时,子类中调用父类方法的代码也需要进行修改;
如果调用的类多,则会使代码量庞大,造成代码冗余。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(Master):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 徒弟类
class Prentice(School):
def __init__(self) -> object:
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
# 一次性调用父类School、Master的方法
def make_old_cake(self):
Master.__init__(self)
Master.make_cake(self)
School.__init__(self)
School.make_cake(self)
# 实例化徒弟对象
daqiu = Prentice()
# 制作煎饼果子
daqiu.make_old_cake()
7.2 通过super()调用
7.2.1 方法一
语法:
super(当前类名, self).方法()
要调用父类的父类的方法,需要在父类的对应方法中调用父类的父类的方法。
该方法的缺陷:
子类的类名修改,相应的代码也要进行修改。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(Master):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 调用父类Master的方法
super(School, self).__init__()
super(School, self).make_cake()
# 徒弟类
class Prentice(School):
def __init__(self) -> object:
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
def make_old_cake(self):
# 调用父类的方法
super(Prentice, self).__init__()
super(Prentice, self).make_cake()
# 实例化徒弟对象
daqiu = Prentice()
# 制作煎饼果子
daqiu.make_old_cake()
7.2.2 方法二
super().方法()
使用super()调用父类方法,可以省略参数。
使用super()可以自动查找父类,调用顺序遵循
__mro__
类属性的顺序。
比较适合单继承使用。
# 师傅类
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 培训机构
class School(Master):
def __init__(self):
self.kongfu = '[Python]'
def make_cake(self):
print(f'运用{self.kongfu}编写程序来制作煎饼果子')
# 调用父类Master的方法
super().__init__()
super().make_cake()
# 徒弟类
class Prentice(School):
def __init__(self) -> object:
self.kongfu = '[Python、煎饼果子配方]'
def make_cake(self):
self.__init__()
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
def make_old_cake(self):
# 调用父类的方法
super().__init__()
super().make_cake()
# 实例化徒弟对象
daqiu = Prentice()
# 制作煎饼果子
daqiu.make_old_cake()
8 私有权限
8.1 定义私有属性和方法
在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
在继承关系中,父类的某些属性或方法不行继承给子类,可以将这些属性或方法设置为私有。
设置私有权限的方法:在属性名和方法名前面加上两个下划线。
默认情况下,父类的所有方法和属性都会继承给子类。
# 徒弟类
class Prentice(object):
def __init__(self) -> object:
self.kongfu = '[Python、煎饼果子配方]'
# 私有属性
self.__money = 20000
def make_cake(self):
print(f'使用{self.kongfu}研究的新技术制作煎饼果子')
# 私有方法
def __info_print(self):
print('私有方法')
# 徒孙类
class TuSun(Prentice):
pass
xiaoqiu = TuSun()
# print(xiaoqiu.money)
xiaoqiu.__info_print()
子类不能访问父类的私有属性和方法。
8.2 获取和修改私有属性值
一般获取和修改类的私有属性值,是在类中进行获取和修改。
在Python中,一般定义函数名get_xxx
用来获取私有属性,定义set_xxx
用来修改私有属性值。
# 徒弟类
class Prentice(object):
def __init__(self):
self.kongfu = '[Python、煎饼果子配方]'
# 私有属性
self.__money = 20000
def get_money(self):
print(self.__money)
def set_money(self, new_money):
self.__money = new_money
daqiu = Prentice()
daqiu.get_money()
daqiu.set_money(1000000)
daqiu.get_money()