一、继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或者多个父类,新建的类可以称为子类或者父类,被继承的类可以称为父类或者基类。
子类可以使用父类中的属性或者方法
解决了类与类之间代码冗余的问题
在python2当中,继承了objcet类的子子孙孙类都称为新式类,没有继承的都称为经典类
在python3中,没有区分经典类和新式类,都是新式类
单继承
只继承一个父类的被称为单继承
单继承下的属性查找
class Foo(): def f2(self): print('from Foo') def f1(self): print('from Foo') class Bar(Foo): def f1(self): print('from f1') # 当该属性或方法在子类中,则使用子类的,如果没有则去父类中寻找,父类中也没有就会报错 obj = Bar() obj.f1() # from f1 obj.f2() # from Foo obj.f3() # 报错
# 练习1
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() # {} obj.f2()
# 练习2 class Foo: def __f1(self): # _Foo__f1() print('Foo.f1') def f2(self): # print('Foo.f2') self.__f1() # _Foo__f1() class Bar(Foo): def __f1(self): # # _Bar__f1() print('Bar.f1') obj = Bar() # {} obj.f2()
多继承
继承多个父类的被称为多继承
多继承下的属性查找
多继承下的属性查找一般分为按照广度查找和按照深度查找
新式类都是按照广度查找的
class G: def test(self): print('from A') class E(G): def test(self): print('from B') pass class F(G): def test(self): print('from C') pass class B(E): def test(self): print('from D') pass class C(F): def test(self): print('from B') pass
class D(G): def test(self): print('from B') pass
class A(B,C,D): def test(self): print('from A') pass print(F.mro()) # 查找顺序 [<class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>] f1 = F() f1.test()
经典类都是按照深度查找顺序查找的
class G: def test(self): print('from A') class E(G): def test(self): print('from B') pass class F(G): def test(self): print('from C') pass class B(E): def test(self): print('from D') pass class C(F): def test(self): print('from B') pass
class D(G): def test(self): print('from B') pass
class A(B,C,D): def test(self): print('from A') pass print(F.mro()) # 查找顺序 [<class '__main__.B'>, <class '__main__.E'>, <class '__main__.G'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>] f1 = F() f1.test()
二、super()和mro列表的使用
super()应用
super()会返回一个特殊的对象,该对象会参考发起属性查找的那一个类的mro列表,依次去当前类的父类中查找属性。
mor列表
mro()会显示类的继承顺序,mor列表会按照从左到右开始查找父类,直到找到第一个匹配这个属性的类为止,类.mro()查看mro列表
class B: def test(self): print('B---->test') def aaa(self): print('B---->aaa') class A: def test(self): print('A---->test') super().test() class C(A, B): def aaa(self): print('C----->aaa') c = C() c.test() # 打印结果: A---->test B---->test print(C.mro())
三、多态与多态性
什么是多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)
例如动物的多种形态:人、狗、猪
# 多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度) # 方式1 class Animal: def run(self): raise Excecption('子类必须实现这个方法') class People(Animal): def run(self): print('人正在走') class Pig(Animal): def run(self): print('pig is walking') class Dog(Animal): def run(self): print('dog is running') peo = People() pig = Pig() d = Dog() peo.run() pig.run() d.run()
# 方式2 import abc class Animal(metaclass=abc.ABCMeta): # 同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): # 动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): # 动物的形态之二:狗 def talk(self): print('say wangwang') class Pig(Animal): # 动物的形态之三:猪 def talk(self): print('say aoao')
什么是多态性
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收 时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
#多态性:一种调用方式,不同的执行效果(多态性) def func(obj): obj.run() func(peo1) func(pig1) func(d1) # peo1.run() # pig1.run() # 多态性依赖于:继承 ##多态性:定义统一的接口, def func(obj): #obj这个参数没有类型限制,可以传入不同类型的值 obj.run() #调用的逻辑都一样,执行的结果却不一样 func(peo1) func(pig1) func(d1)
总结
多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度) 多态性:一种调用方式,不同的执行效果(多态性)
三、为什么要用多态性(多态性的好处)
(1)增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
(2)增加了程序额可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用