-
继承
-
什么是继承:两个对象之间的关系,一个称为子类,一个称为父类,其中子类继承着父类的属性以及方法技能,可以直接使用。(值得注意的是:在python3中所有创建的类都直接或间接,隐性或显性的继承object类,如果没有显示继承某个类,则默认继承的是object类,又称为新式类)
-
为什么要使用继承:减少代码的复用
-
用代码如何表示
-
class Base: character = '我是父类' def want_basketball(self): print('教练我想打篮球') class SubClass(Base): # 通过在子类的括号之中加父类的名称 pass obj = SubClass() obj.want_basketball() # 直接调用父类的方法 如果属性和方法完全一样的话 print(obj.character)
比如好人,坏人,黄种人,白种人,黑人都是人这个大类的继承,而他们都是抽象而生成人这个类的。
-
那么当子类和父类有属性和方法有冲突时,是不是就不可以用继承方法呢?显然不是,一般来说我们可以将子类和父类的共同特征都提取出来,专业名词可以称之为抽象,将抽象完的一个新的类作为共同大类,供上述子类和父类使用。
- 就以足球和篮球运动员为例,对于他们来说都是人类,都有名字性别和身高等特征,但是他们会的技能不一样
-
class Person: def __init__(self,name,height,gender): # 定义抽象得来的公共类 self.name = name self.height = height self.gender = gender class FootBallPlayer(Person): # 通过子类名括号里面加抽象父类名起到继承的作用 def Skill(self): print('%s会踢足球'%(self.name)) class BasketBallPlayer(Person): def Skill1(self): print('%s会打篮球'%(self.name)) Kobe = BasketBallPlayer('kobe Bryant','189','male') # 名字身高等信息就不需要通过父类调用,直接子类调用 Kobe.Skill1() Messi = FootBallPlayer('Lion Messi','176','male') Messi.Skill()
-
存在继承关系后的属性查找
-
一个类必然继承另一个类,被继承的类也有可能继承了其他类,相当于C继承B,B又继承A
-
此时查找属性的顺序是:
对象本身的名称空间 - > 类的名称空间 -> 父类的名称空间 -> 父类的父类名称空间 ->...object类
会沿着继承关系一直往后查找,直到找到为止,由于object是所有类的根类,所以如果找不着最后都会查找object类!
-
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') b=Bar() b.f1() #输出 Bar.f1 b.f2() #输出 Foo.f2
-
派生和覆盖
-
派生的定义:当父类提供的属性无法完全满足子类的需求时,子类可以增加自己的属性或方法,或者覆盖父类已经存在的属性,此时子类称之为父类的派生类;
- 覆盖的定义:如果子类中出现于与父类相同的属性以及方法时,程序要调用,会优先使用子类中的属性。
-
很多情况下 子类中的代码与父类中仅有小部分不同,却不得不在子类定义新的方法,这时候可以在子类中调用父类已有的方法,来完成大部分工作,子类仅需编写一小部分与父类不同的代码即可
-
有两种方式可以重用父类的属性和方法
- 使用类名直接调用 ,该方式与继承没有关系,即时没有继承关系,也可以调用
- 使用super()
-
class Person: def __init__(self,name,height,gender): # 定义抽象得来的公共类 self.name = name self.height = height self.gender = gender class FootBallPlayer(Person): # 通过子类名括号里面加抽象父类名起到继承的作用 def __init__(self,name,height,gender,field): # 如果不写这两行 将不能调用name height gender属性 super().__init__(name,height,gender) # 重用父类中的代码,防止覆盖了父类中的init方法 self.field = field def Skill(self): print('%s会踢足球'%(self.name)) print(self.height,self.gender,self.field)
Messi = FootBallPlayer('Lion Messi','176','male','grass')
Messi.Skill() -
组合
-
当两个类之间没有太大的联系的时候,或者说它们不属于同类时,当一个对象要使用另一个对象的属性,这就叫做组合的概念。
-
class Equip: # 武器装备类 def fire(self): print('release Fire skill') class Riven: # 英雄Riven的类,一个英雄需要有装备,因而需要组合Equip类 camp = 'Noxus' def __init__(self, nickname): self.nickname = nickname self.equip = Equip() # 用Equip类产生一个装备,赋值给实例的equip属性 r1 = Riven('锐雯雯') r1.equip.fire() # 可以使用组合的类产生的对象所持有的方法
-
继承实现的原理
-
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类 继承顺序
-
继承实质
- python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如
-
>>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>
-
所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类