面向对象的三大特性:封装、继承、多态---->单继承、多继承 第十九天 2018.11.4
上节复习:
面向对象编程:
思想:角色的抽象,创建类,创建角色(实例化),操作这些实例
面向对象的关键字:
class 类名:
静态属性=' '
def __init__(self):
类名.静态属性 ——> 存储在类的命名空间里
对象 = 类名() 实例化:创造了一个self对象,执行init方法,返回self对象给外部
对象.属性
对象.方法 类名.方法(对象)
对象可以使用静态变量 类不可以使用对象里的属性
组合:一个类的对象是另外一个类对象的属性
面向对象的三大特性:封装、继承、多态
继承:直接在类名后加括号,括号里面便是该类的父类,父类可以有多个(Python支持多继承);
父类又可以称为基类、超类;Python中所有最高级父类的默认继承为object(新式类),最高级父类可以不带括号。
class A(object):pass # 父类,基类,超类 默认继承object(新式类) class B:pass # 父类,基类,超类 class A_son(A,B):pass # 子类,派生类 class AB_son(A):pass # 子类,派生类
单继承:一个父类 可以被多个子类继承
多继承:一个子类 可以继承多个父类
.__bases__查看该类所有父类,没有的话默认object
print(A_son.__bases__) #.__bases__查看该类的所有父类 print(AB_son.__bases__) print(A.__bases__) # python3 -新式类# 没有继承父类默认继承object
抽象:抽取类似或者说比较像的部分
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp self.func() #作为一个对象调用方法,此处self为dog的,相当于Dog.func() def func(self): print(123) class Dog(Animal): def func(self): #在此创建Dog的self对象,因为Dog中无__init__()方法,因此向父类中找init方法 print(456) #456 def bite(self,person): person.hp -= self.aggr d = Dog() #执行Dog类 class Person(Animal): def __init__(self,name,aggr,hp,sex): Animal.__init__(self,name,aggr,hp) self.sex = sex # 派生属性 self.money = 0 # 派生属性 def attack(self,dog): dog.hp -= self.aggr def get_weapon(self,weapon): if self.money >= weapon.price: self.money -= weapon.price self.weapon = weapon self.aggr += weapon.aggr else: print("余额不足,请先充值") alex = Person('alex',1,2,None) alex.eat() print(alex.hp) jin.bite(alex) print(alex.hp)
派生:父类中没有的子类中出现了的
父类中没有的属性 在子类中出现 叫做派生属性
父类中没有的方法 在子类中出现 叫做派生方法
只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
如果父类 子类都有 用子类的
如果还想用父类的,单独调用父类的:
父类名.方法名 需要自己传self参数
super().方法名 不需要自己传self
正常的代码中 单继承 === 减少了代码的重
继承表达的是一种 子类是父类的关系
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print('吃药回血') self.hp+=100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): Animal.__init__(self,name,aggr,hp) # self.kind = kind # 派生属性 def eat(self): Animal.eat(self) # 如果既想实现新的功能也想使用父类原本的功能,还需要在子类中再调用父类 self.teeth = 2 def bite(self,person): # 派生方法 pass jin = Dog('金老板',100,500,'吉娃娃') jin.eat() print(jin.hp)
class Animal: def __init__(self,name,aggr,hp): self.name = name self.aggr = aggr self.hp = hp def eat(self): print('吃药回血') self.hp+=100 class Dog(Animal): def __init__(self,name,aggr,hp,kind): super().__init__(name,aggr,hp) # 只在新式类中有,python3中所有类都是新式类 self.kind = kind # 派生属性 def eat(self):print('dog eating') jin = Dog('金老板',200,500,'teddy') print(jin.name) jin.eat() super(Dog,jin).eat()
多继承:(.mro()查看调用方法时经过父类的顺序)
新式类 继承object类的才是新式类 广度优先
经典类 如果你直接创建一个类在2.7中就是经典类 深度优先
单继承 : 子类有的用子类 子类没有用父类
多继承中,我们子类的对象调用一个方法,默认是就近原则,找的顺序是:经典类中 深度优先;新式类中 广度优先
python2.7 新式类和经典类共存,新式类要继承object(即出现父类后括号里object)
python3 只有新式类,默认继承object
经典类和新式类还有一个区别 mro方法只在新式类中存在
super 只在python3中存在
super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的
钻石继承、漏斗继承:
六边形继承:
class F: def func(self): print('F') class A(F):pass # def func(self): print('A') class B(A): pass # def func(self): print('B') class E(F):pass # def func(self): print('E') class C(E): pass # def func(self): print('C') class D(B,C): pass # def func(self):print('D') d = D() # d.func() print(D.mro())
新式类中的继承顺序:广度优先(加super().):
class A(object): def func(self): print('A') #所以第一个输出A class B(A): def func(self): #不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的 super().func() #此时调用者节点位置为B按广度优先顺序再到C print('B') #第三个输出B class C(A): #此时调用者节点位置为C按广度优先顺序该到最后节点A def func(self): super().func() print('C') #第二个输出C class D(B,C): #此时调用者节点位置为D按广度优先顺序先到B def func(self): super().func() print('D') #最后输出D b = D() b.func() print(B.mro())