目录python
在 python 中,一个子类能够继承多个父类,其余语言只能一个子类继承一个父类。编程
目的:减小代码冗余(减小重复代码)编程语言
先肯定谁是子类,谁是父类函数
在定义类时,子类 + (),括号内填父类的名字,实现继承设计
使用 __bases__
方法,能够获取当前类所继承的类3d
class Father1: pass class Father2: pass class Son1(Father1): pass class Son2(Father1, Father2): pass print(Son1.__bases__) # 查看父类 print(Son2.__bases__)
运行结果:code
(<class '__main__.Father1'>,) (<class '__main__.Father1'>, <class '__main__.Father2'>) Process finished with exit code 0
继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承,抽象即抽取相似或者说比较像的部分。对象
抽象分红两个层次:blog
抽象最主要的做用是划分类别(能够隔离关注点,下降复杂度),以下图所示:继承
继承:基于抽象的结果,经过编程语言去实现它,确定是先经历抽象这个过程,才能经过继承的方式去表达出抽象的结构。
抽象只是分析和设计的过程当中,一个动做或者说一种技巧,经过抽象能够获得类,以下图所示:
在继承背景下,对象属性的查找顺序:
注意:对象查找属性,若子类有,无论父类有没有,以子类的为准。
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') # 对象查找属性的顺序:对象本身-》对象的类-》父类-》父类。。。 obj = Bar() # self是obj自己,即找到Bar的f1() obj.f2()
运行结果:
Foo.f2 Bar.f1 Process finished with exit code 0
子类中新定义的属性的这个过程叫作派生,而且须要记住子类在使用派生的属性时始终以本身的为准。
指名道姓访问某一个类的函数:该方式与继承无关
# 直接经过 父类.(调用)__init__,把__init__当作普通函数使用,传入对象与继承的属性. class Father: def __init__(self, name, age): self.name = name self.age = age class Son(Father): def __init__(self, name, age, weight, height): Father.__init__(self, name, age) self.weight = weight self.height = height
super()
方法super()
会获得一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)super().__init__
(不用为self传值)super()
的完整用法是 super(本身的类名,self)
,在python2中须要写完整,而python3中能够简写为 super()
class Father: def __init__(self, name, age): self.name = name self.age = age class Son(Father): def __init__(self, name, age, weight, height): super().__init__(name, age) self.weight = weight self.height = height
在 python2 中,才有才会有新式类与经典类之分;在 python3 中,全部的类都是新式类。
继承 object 的类都称之为新式类。
在 python3 中,若是子类没有继承自定义的类,都默认继承 object 。
class Foo(): pass class Goo(Foo): pass print(Foo.__bases__) print(Goo.__bases__)
运行结果:
(<class 'object'>,) # 默认继承 object (<class '__main__.Foo'>,) Process finished with exit code 0
在 python2 中,凡是没有继承 object 的类都是经典类。
在Java和C#中子类只能继承一个父类,而Python中子类能够同时继承多个父类,如A(B,C,D)
若是继承关系为非菱形结构,则会按照先找B这一条分支,而后再找C这一条分支,最后找D这一条分支的顺序直到找到咱们想要的属性
若是继承关系为菱形结构,即子类的父类最后继承了同一个类,那么属性的查找方式有两种:
经典类:一条路走到黑,深度优先
新式类:不找多各种最后继承的同一个类,直接去找下一个父类,广度优先
可使用下面的代码逐一进行验证:
# 验证 class A: def test(self): print('from A') pass class B(A): def test(self): print('from B') pass class C(A): def test(self): print('from C') pass class D(B): def test(self): print('from D') pass class E(C): def test(self): print('from E') pass class F(D, E): def test(self): print('from F') pass f1 = F() f1.test()
结果:
# 新式类: F-D-B-E-C-A-object # 经典类: F-D-B-A-E-C
mro()
方法对于多继承的类,python 提供了 mro()
方法,便捷的查看继承的查找顺序。
对于上述代码,咱们可使用 mro()
方法:
# print(F.mro()) # 新式类下: for i in F.mro(): print(i)
运行结果:
<class '__main__.F'> <class '__main__.D'> <class '__main__.B'> <class '__main__.E'> <class '__main__.C'> <class '__main__.A'> <class 'object'> Process finished with exit code 0