• 面向对象——继承,派生


    1.继承

    • 继承指的是类与类之间的关系,是一种什么“是”什么的关系,继承的功能之一就是用来解决代码重用问题
    • 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可以成为基类或超类,新建的类称为派生类或子类
    • 单继承和多继承
    •  1 class ParentClass1:
       2     pass
       3 class ParentClass2:
       4     pass
       5 class SubClass1(ParentClass1):#单继承
       6     pass
       7 class SubClass2(ParentClass1,ParentClass2):#多继承
       8     pass
       9 
      10 #查看继承
      11 print(SubClass1.__bases__)#(<class '__main__.ParentClass1'>,)
      12 print(SubClass2.__bases__)#(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
      13 #__bases__与__base__的区别
      14 print(SubClass2.__base__)#<class '__main__.ParentClass1'>,只能查看从左到右继承的第一个子类

    2.经典类与新式类

     1 #在python2中,经典类:没有继承object的类,以及它的子类都称为经典类
     2 # class Foo:
     3 #     pass
     4 # class Bar(Foo):
     5 #     pass
     6 #在python2中,新式类:继承object的类,以及它的子类都称为新式类
     7 # class Foo(object):
     8 #     pass
     9 # class Bar(Foo):
    10 #     pass
    11 
    12 #在python3中,都是新式类,一个类没有继承object,默认继承object
    13 # class Foo:#默认继承object,
    14 #     pass
    15 # class Bar(Foo):
    16 #     pass
    17 # print(Foo.__bases__)#(<class 'object'>,)

    3.继承与抽象(先抽象再继承)

    • 抽象:抽取类似或者说比较像的部分,抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
    • 继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构
    • 抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

     

    4.继承与重用性

    • 在开发程序的过程中,如果已经定义了类A,又想新建立一个类B,但是类B的大部分内容与类A相同,可以通过继承的方式新建类B,让B继承A,B会“遗传”A的所有属性(数据属性和函数属性),实现代码重用,大大节省编程工作量。
    • 常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就大大缩短了软件开发周期,对大型软件开发来说,意义重大
    •  1 #继承属性查找
       2 class Foo:
       3     def f1(self):
       4         print("form Foo.f1")
       5     def f2(self):
       6         print("form Foo.f2")
       7         self.f1()
       8 class Bar(Foo):
       9     def f1(self):
      10         print("form Bar.f1")
      11 b = Bar()
      12 b.f2()
      13 #form Foo.f2   #显而易见,不用解释
      14 #form Bar.f1  #解释:在运行self.f1()时,其实就是b.f1(),所以按照继承顺序,优先从Bar类中找,而不是就近原则,
      15 # 因此打印的是form Bar.f1
      16 print(Bar.mro())
      17 #[<class '__main__.Bar'>, <class '__main__.Foo'>, <class 'object'>]
      继承属性查找

    5.派生

    • 子类可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了
    • 在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值
    •  1 class Riven(Hero):
       2     camp='Noxus'
       3     def __init__(self,nickname,aggressivity,life_value,skin):
       4         Hero.__init__(self,nickname,aggressivity,life_value) #调用父类功能
       5         self.skin=skin #新属性
       6     def attack(self,enemy): #在自己这里定义新的attack,不再使用父类的attack,且不会影响父类
       7         Hero.attack(self,enemy) #调用功能
       8         print('from riven')
       9     def fly(self): #在自己这里定义新的
      10         print('%s is flying' %self.nickname)
      View Code

    6.继承的实现原理

    • 对于定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。
    • 经典类:多继承情况下,在要查找属性不存在时,会按照深度优先的方式查找下去,没有mro()方法
    • 经典类
    • 新式类:多继承情况下,在要查找属性不存在时,会按照广度有限的方式查找下去,可通过mro()方式查询继承顺序
    • 新式类
    •  1 class A(object):
       2     def test(self):
       3         print('from A')
       4     pass
       5 
       6 class B(A):
       7     def test(self):
       8         print('from B')
       9     pass
      10 
      11 class C(A):
      12     def test(self):
      13         print('from C')
      14     pass
      15 
      16 class D(B):
      17     def test(self):
      18         print('from D')
      19     pass
      20 
      21 class E(C):
      22     def test(self):
      23         print('from E')
      24     pass
      25 
      26 class F(D,E):
      27     def test(self):
      28         print('from F')
      29     pass
      30 f1=F()
      31 f1.test()
      32 # print(F.mro())# F > D > B > E > C > A > object
      33 #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>,
      34 # <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
      35 print(F.__bases__)#(<class '__main__.D'>, <class '__main__.E'>)
      36 
      37 #经典类没有提供mro()方法
      pyt3新式类示例
    • 为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。这个MRO列表的构造是通过一个C3线性算法来实现的,只在新式类中有,遵循如下三条准则
      • 子类会先于父类被检查
      • 多个父类会根据它们在列表中的顺序被检查
      • 如果对下一个类存在两个合法的选择,选择第一个父类

    7.在子类中调用父类的方法

    • 方式一:指名道姓,即父类名.父类方法(),不依赖于继承
    •  1 #方式一
       2 class Vehicle:#定义交通工具类
       3     country = "China"
       4     def __init__(self,name,speed,load,power):
       5         self.name = name
       6         self.speed = speed
       7         self.load = load
       8         self.power = power
       9     def run(self):
      10         print("开动啦。。。")
      11 class Subway(Vehicle):
      12     def __init__(self,name,speed,load,power,line):
      13         Vehicle.__init__(self,name,speed,load,power)#self一定要传
      14         self.line = line
      15     def run(self):
      16         print('地铁%s号线欢迎您' %self.line)
      17         Vehicle.run(self)#self一定要传
      18 line13 = Subway('中国地铁','180m/s','1000人/箱','',13)
      19 line13.run()
      20 # 地铁13号线欢迎您
      21 # 开动啦。。。
      方式一
    • 方式二:super(),依赖于继承
    •  1 #方式二
       2 class Vehicle:#定义交通工具类
       3     country = "China"
       4     def __init__(self,name,speed,load,power):
       5         self.name = name
       6         self.speed = speed
       7         self.load = load
       8         self.power = power
       9     def run(self):
      10         print("开动啦。。。")
      11 class Subway(Vehicle):
      12     def __init__(self,name,speed,load,power,line):
      13         # super(Subway, self).__init__(name,speed,load,power)
      14         super().__init__(name,speed,load,power)
      15         #super(Subway, self)就相当于实例本身,在python3中super()等于super(Subway, self)
      16         self.line = line
      17     def run(self):
      18         print('地铁%s号线欢迎您' %self.line)
      19         # super(Subway, self).run()
      20         super().run()
      21 line13 = Subway('中国地铁','180m/s','1000人/箱','',13)
      22 line13.run()
      View Code
    • 区别:方式一是跟继承没有关系的,而方式二的super()是依赖于继承的,并且即使没有直接继承关系,super依然会按照mro继续往后查找
    •  1 class A:
       2     def test(self):
       3         super().test()
       4 class B:
       5     def test(self):
       6         print("from B")
       7 class C(A,B):
       8     pass
       9 
      10 c = C()
      11 c.test()#from B
      12 print(C.mro())
      13 # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
      View Code
  • 相关阅读:
    编程语言学哪个比较好?
    C#一定要避免程序中很多的依靠
    EXPIREAT
    EXISTS
    DUMP
    Python之sys模块
    Python的OS模块
    CentOS 7上安装gitlab-runner
    PyCharm激活方法
    Linux03 文件的相关操作(touch、rm、mv、cat)
  • 原文地址:https://www.cnblogs.com/GraceZ/p/8066779.html
Copyright © 2020-2023  润新知