Python面向对象之派生
1499 字
7 分钟
Python面向对象之派生
【一】什么是派生
- 派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法
【二】派生的方法
- 子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
- 例如每个老师还有职称这一属性
- 我们就需要在Teacher类中定义该类自己的__init__覆盖父类的
- 当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
class People: school = '清华大学'
def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age
class Teacher(People): # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找 def __init__(self, name, sex, age, title): self.name = name self.sex = sex self.age = age self.title = title
def teach(self): print('%s is teaching' % self.name)
# 只会找自己类中的__init__,并不会自动调用父类的obj = Teacher('dream', 'male', 18, '高级讲师')
print(obj.name, obj.sex, obj.age, obj.title)# dream male 18 高级讲师- 很明显子类Teacher中__init__内的前三行又是在写重复代码
- 若想在子类派生出的方法内重用父类的功能,有两种实现方式
【1】指名道姓的调用某一个类的函数
class People: school = '清华大学'
def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age
class Teacher(People): # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找 def __init__(self, name, sex, age, title): # 直接调用 父类 中 的 __init__ 方法 # 调用的是函数,因而需要传入self People.__init__(self, name, age, sex) self.title = title
def teach(self): print('%s is teaching' % self.name)
# 只会找自己类中的__init__,并不会自动调用父类的obj = Teacher('dream', 'male', 18, '高级讲师')
print(obj.name, obj.sex, obj.age, obj.title)# dream male 18 高级讲师【2】超类(super())
- 调用super()会得到一个特殊的对象
- 该对象专门用来引用父类的属性
- 且严格按照MRO规定的顺序向后查找
class People: school = '清华大学'
def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age
class Teacher(People): # 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找 def __init__(self, name, sex, age, title): # 直接调用 父类 中 的 __init__ 方法 # 调用的是绑定方法,因此会自动传入self,但是需要传入相应的参数 super().__init__(name, sex, age) self.title = title
def teach(self): print('%s is teaching' % self.name)
# 只会找自己类中的__init__,并不会自动调用父类的obj = Teacher('dream', 'male', 18, '高级讲师')
print(obj.name, obj.sex, obj.age, obj.title)# dream male 18 高级讲师- 提示:在Python2中super的使用需要完整地写成super(自己的类名,self) ,而在python3中可以简写为super()。
- 当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。
- 只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次
- (注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)
【3】小结
- 这两种方式的区别是:
- 方式一是跟继承没有关系的,而方式二的super()是依赖于继承的
- 并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找
# A没有继承Bclass A: def test(self): super().test()
class B: def test(self): print('from B')
class C(A, B): pass
# 在代码层面A并不是B的子类# 但从MRO列表来看,属性查找时,就是按照顺序C->A->B->object,B就相当于A的“父类”print(C.mro())# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
obj = C()
# 属性查找的发起者是类C的对象obj# 所以中途发生的属性查找都是参照C.mro()obj.test()# from B- obj.test()首先找到A下的test方法
- 执行super().test()会基于MRO列表(以C.mro()为准)当前所处的位置继续往后查找()
- 然后在B中找到了test方法并执行。
- 关于在子类中重用父类功能的这两种方式
- 使用任何一种都可以
- 但是在最新的代码中还是推荐使用super()
#指名道姓class A: def __init__(self): print('A的构造方法')class B(A): def __init__(self): print('B的构造方法') A.__init__(self)
class C(A): def __init__(self): print('C的构造方法') A.__init__(self)
class D(B,C): def __init__(self): print('D的构造方法') B.__init__(self) C.__init__(self)
passf1=D() #A.__init__被重复调用'''D的构造方法B的构造方法A的构造方法C的构造方法A的构造方法'''#使用super()class A: def __init__(self): print('A的构造方法')class B(A): def __init__(self): print('B的构造方法') super(B,self).__init__()
class C(A): def __init__(self): print('C的构造方法') super(C,self).__init__()
class D(B,C): def __init__(self): print('D的构造方法') super(D,self).__init__()
f1=D() #super()会基于mro列表,往后找'''D的构造方法B的构造方法C的构造方法A的构造方法'''【4】小练习
# A没有继承B,但是A内super会基于C.mro()继续往后找class A: def test(self): print('A---->test') super().aaa()
class B: def test(self): print('B---->test')
def aaa(self): print('B---->aaa')
class C(A, B): def aaa(self): print('C----->aaa')
c = C()c.test()# 打印结果:'''A---->testB---->aaa'''
# C作为方法调用(即c.test())的发起者,方法调用过程中涉及的属性查找都参考C.mro()。# 父子关系按照mro列表为准,千万不要从代码层面看父子。例如print(C.mro())# c.test(),发起者C.mro()列表如下# 从列表中可以看出,B类就是A类他爹,而代码层面二者并无继承关系# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!
相关文章智能推荐
1
C 语言发展史
编程语言了解 C 语言从 BCPL、B 语言到现代标准 C 的发展历程、核心特点与应用领域。
2
C 语言开发环境的安装与配置
编程语言在 Windows、Linux 与 macOS 上安装 C 工具链,配置编辑器,并编译运行第一个 C 程序。
3
C 语言初识:程序运行机制与基本结构
编程语言认识 C 程序从源代码到运行的完整流程,以及基础语法和程序的基本结构。
4
C 语言基础:注释、关键字、变量与数据类型
编程语言学习 C 语言的注释、关键字、标识符、常量、变量和基本数据类型等基础知识。
5
C 语言数据类型
编程语言理解 C 语言的数据类型体系,包括基本类型、整数类型、浮点类型和逻辑类型。
随机文章随机推荐














