面向对象——继承

1、什么是继承?

继承一种新建类的方式,新建的类称之为子类/派生类,被继承的类称之为父类基类超类

# 将所有共有的属性与方法抽离出,形成父类
# 父类是多个有共同点的普通类抽离共有属性与方法形成的类


2.python中继承的特点:

  1 python中继承的特点:
  2         1. 子类可以遗传/重用父类的属性
  3         2. python中一个子类可以同时继承多个父类
  4         3. 在继承背景下去说,python中的类分为两种:新式类,经典类
  5             新式类: 但凡继承了object的类Foo,以及该类的子类...都是新式类
  6                 在python3中一个类即便是没有显式地继承任何类,默认就会继承object
  7                 即python3中所有的类都是新式类
  8 
  9             经典类:没有继承object的类,以及该类的子类...都是经典类
 10                 在python2中才区分新式类与经典类,
 11                 在python2中一个类如果没有显式地继承任何类,也不会继承object

3 为何要用继承
    减少类与类之间代码冗余

3 如何用继承

# 继承的规则
# 1.父类的所有未封装的属性和方法,子类都能访问
# 2.父类的所有封装的属性和方法,子类都不能访问
#       -- 在外界通过子类或子类对象,不能访问
#       -- 在子类内部通过子类或子类对象也不能访问

语法

  1 # class Parent1(object):
  2 #     pass
  3 #
  4 # class Parent2(object):
  5 #     pass
  6 #
  7 # class Sub1(Parent1):
  8 #     pass
  9 #
 10 # class Sub2(Parent1,Parent2):
 11 #     pass
 12 
 13 # print(Parent1.__bases__)
 14 # print(Parent2.__bases__)
 15 # print(Sub1.__bases__)
 16 # print(Sub2.__bases__)

3.1利用继承来解决代码之间的冗余问题
例子

  1 class OldboyPeople:
  2     school = 'Oldboy'
  3 
  4     def __init__(self,name,age,sex):
  5         self.name = name
  6         self.age = age
  7         self.sex = sex
  8 
  9 class OldboyStudent(OldboyPeople):
 10     # def __init__(self, name, age, sex, score=0):
 11     #     self.name = name
 12     #     self.age = age
 13     #     self.sex = sex
 14     #     self.score = score
 15 
 16     def choose_course(self):
 17         print('%s choosing course' % self.name)
 18 
 19 class OldboyTeacher(OldboyPeople):
 20     # def __init__(self,name,age,sex,level):
 21     #     self.name=name
 22     #     self.age=age
 23     #     self.sex=sex
 24     #     self.level=level
 25 
 26     def score(self,stu,num):
 27         stu.score=num
 28 
 29 
 30 stu1=OldboyStudent('刘二蛋',38,'male')
 31 print(stu1.__dict__)
 32 
 33 tea1=OldboyTeacher('egon',18,'male')
 34 print(tea1.__dict__)
 35 
View Code

3.2 父类功能的重用

在子类派生出的新方法中重用父类功能的方式一:

# 指名道姓地引用某一个类中的函数
# 总结:
# 1. 与继承无关
# 2. 访问是类的函数,没有自动传值的效果

  1 class OldboyPeople:
  2     school = 'Oldboy'
  3 
  4     def __init__(self,name,age,sex):
  5         self.name = name
  6         self.age = age
  7         self.sex = sex
  8 
  9 class OldboyStudent(OldboyPeople):
 10     def __init__(self, name, age, sex, score=0):
 11         OldboyPeople.__init__(self,name,age,sex)
 12         self.score = score
 13 
 14     def choose_course(self):
 15         print('%s choosing course' % self.name)
 16 
 17 class OldboyTeacher(OldboyPeople):
 18     def __init__(self,name,age,sex,level):
 19         OldboyPeople.__init__(self,name,age,sex)
 20         self.level=level
 21 
 22     def score(self,stu,num):
 23         stu.score=num
 24 
 25 
 26 stu1=OldboyStudent('刘二蛋',38,'male')
 27 print(stu1.__dict__)
 28 
 29 tea1=OldboyTeacher('egon',18,'male',10)
 30 print(tea1.__dict__)
 31 
 32 
View Code

在子类派生出的新方法中重用父类功能的方式二:super()必须在类中用
 

  1 class Sup:
  2     def __init__(self, name):
  3         self.name = name
  4 
  5     def test(self):
  6         print(self)
  7 
  8 
  9 class Sub(Sup):
 10     # 默认父级的__init__可以被继承过来,
 11     # 但是会出现子类对象的属性比父类多
 12     def __init__(self, name, salary):
 13         super().__init__(name)  # 父级有的共性功能通过super()交给父级做
 14         self.salary = salary  # 子类特有的自己来完成
 15 
 16     # 有继承关系下,只要名字相同,即使参数不同,还是属于同一个方法
 17     def test(self, num):
 18         super().test()  # 使用父级的方法
 19         print(num)
 20 
 21 # 外界通过Sub对象来调用test方法,一定找自己的test方法(属性的查找顺序)
 22 
 23 
 24 # 重点:super() 可以得到调用父级功能的对象,调用者还是子类对象
 25 # 		-- super()只能在子类的方法中使用
 26 #		-- super()本质 super(子类类名, 当前对象)
 27 #		-- super().父类普通方法 | super().__init__() | super()能调用父类所有可继承方法
View Code

# 在python2中:super(自己的类名,自己的对象)
# 在python3中:super()
# 调用该函数会得到一个特殊的对象,该对象专门用来访问父类中的属性,!!!完全参照mro列表!!!!
# 总结:
# 1. 严格依赖继承的mro列表
# 2. 访问是绑定方法,有自动传值的效果

  1 # class OldboyPeople:
  2 #     school = 'Oldboy'
  3 #
  4 #     def __init__(self,name,age,sex):
  5 #         self.name = name
  6 #         self.age = age
  7 #         self.sex = sex
  8 #
  9 # class OldboyStudent(OldboyPeople):
 10 #     def __init__(self, name, age, sex, score=0):
 11 #         super(OldboyStudent,self).__init__(name,age,sex)
 12 #         self.score = score
 13 #
 14 #     def choose_course(self):
 15 #         print('%s choosing course' % self.name)
 16 #
 17 # class OldboyTeacher(OldboyPeople):
 18 #     def __init__(self,name,age,sex,level):
 19 #         super().__init__(name,age,sex)
 20 #         self.level=level
 21 #
 22 #     def score(self,stu,num):
 23 #         stu.score=num
 24 
 25 
 26 # stu1=OldboyStudent('刘二蛋',38,'male')
 27 # print(stu1.__dict__)
 28 #
 29 # tea1=OldboyTeacher('egon',18,'male',10)
 30 # print(tea1.__dict__)
View Code

4.单继承背景下的属性的查找
     在单继承背景下属性的查找优先级:对象->对象的类->父类->父类.....

  1 class Foo:
  2     def f1(self):
  3         print('Foo.f1')
  4 
  5     def f2(self):
  6         print('Foo.f2')
  7         self.f1() #obj.f1()
  8 
  9 class Bar(Foo):
 10     def f1(self):
 11         print('Bar.f1')
 12 
 13 obj=Bar()
 14 obj.f2()
 15 '''
 16 Foo.f2
 17 Bar.f1
 18 '''
View Code

5

# 在多继承背景下属性的查找优先级:
# 如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)
# 此时属性的查找优先级是:对象->对象的类->按照从左往右的顺序一个分支一个分支的找下去

  1 
  2 # # 第四层:
  3 # class G:
  4 #     # x = 'G'
  5 #     pass
  6 #
  7 # # 第三层
  8 # class E(G):
  9 #     # x = 'E'
 10 #     pass
 11 #
 12 # class F:
 13 #     # x = 'F'
 14 #     pass
 15 #
 16 # # 第二层
 17 # class B(E):
 18 #     # x = 'B'
 19 #     pass
 20 #
 21 # class C(F):
 22 #     # x = 'C'
 23 #     pass
 24 #
 25 # class D:
 26 #     # x = 'D'
 27 #     pass
 28 #
 29 # # 第一层
 30 # class A(B, C, D):
 31 #     # x = 'A'
 32 #     pass
 33 #
 34 # obj = A()
 35 # # obj.x = 111
 36 # print(obj.x)
 37 
View Code

#菱形继承问题:
# 新式类 : 广度优先查找,从左往右一个分支一个分支的查找,在最后一个分支才去查找顶级类
# 经典类 : 深度优先查找,从左往右一个分支一个分支的查找,在第一个分支就查找顶级类

  1 class G(object):
  2     # x = 'G'
  3     pass
  4 
  5 # 第三层
  6 class E(G):
  7     # x = 'E'
  8     pass
  9 
 10 class F(G):
 11     # x = 'F'
 12     pass
 13 
 14 # 第二层
 15 class B(E):
 16     # x = 'B'
 17     pass
 18 
 19 class C(F):
 20     # x = 'C'
 21     pass
 22 
 23 class D(G):
 24     # x = 'D'
 25     pass
 26 
 27 # 第一层
 28 class A(B, C, D):
 29     # x = 'A'
 30     pass
 31 
 32 
 33 obj=A()
 34 # obj.x=111
 35 print(obj.x)
 36 #新式类(广度优先): obj->A->B->E->C-F->D->G->object
 37 #经典类(深度优先): obj->A->B->E->G->C-F->D
 38 
 39 # python专门为新式类内置了一个mro的方法,用来查看c3算法的计算结果,结果是??
 40 print(A.mro())
View Code
原文地址:https://www.cnblogs.com/king-home/p/10759858.html