Tiny_Lu
不忘初心

Day 20 继承/派生/菱形继承/新式类和经典类

类的继承

什么是继承

继承就是新建类的方法,新建的类被称为子类或者派生类

子类继承的类叫做父类,也称之为基类或者超类

继承的特征

子类可以继承父类的属性(特征与技能),并且可以派生出自己的属性(特征与技能)

注意:在python中子类可以同事继承多个父类,其他语言只能一个子类继承一个父类

为什么要继承

继承的目的是为了减少代码的冗余(减少代码重复)

如何实现继承

  1. 首先要确定谁是子类,谁是父类
  2. 在定义类时,子类+(), ()内写父类,实现继承
# 父类
class ParentClass1():
    pass

class ParentClass2():
    pass

# 子类
class ChildClass1(ParentClass1):
    pass

# 继承多个父类
class ChildClass2(ParentClass1, ParentClass2):
    pass

# __bases__是类的属性,用来查看子类的父类
print(ChildClass1.__bases__)

print(ChildClass2.__bases__)
(<class '__main__.ParentClass1'>,)
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

继承的关系

继承与抽象

继承描述的是子类和父类之间的关系,是一种什么是什么的关系.要找出这种关系,必须先抽象再继承,抽象即抽取类似或者比较像的部分.

抽象分成两个层次:

  1. 将对象间比较像的部分抽取成类
  2. 将类间比较像的部分抽取成父类

抽象最重要的作用是划分类别

# 选课系统
class OldboyTeacher():
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        
    def change_score(self):
        print('change_score')
        
class OldboyStudent():
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        
    def choose_course(self, course):
        print('{self.name}选择{course}课程')

两个类具有相同的__init__,所以我们可以抽取出一个父类

# 选课系统
class OldboyPeople:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class OldboyTeacher(OldboyPeople):   
    def change_score(self):
        print('change_score')
        
class OldboyStudent(OldboyPeople):   
    def choose_course(self, course):
        print('{self.name}选择{course}课程')
        

stu1 = OldboyStudent('Tiny', 18, 'male')
tea1 = OldboyTeacher('nick', 20, 'male')
print(stu1.name, stu1.age, stu1.gender)
print(tea1.name, tea1.age, tea1.gender)
Tiny 18 male
nick 20 male

属性查找顺序

class Foo:
    def f1():
        print('Foo.f1')
        
    def f2():
        print('Foo.f2')
        self.f1()
        
class Soo(Foo):
    def f1():
        print('Soo.f1')
        
soo = Soo()
soo.f2()
Foo.f2
Soo.f1

对象查找属性的顺序:对象自己 ---> 对象的类 ---> 父类 ---> 父类 ---> ... ---> 报错

类的派生

派生:

子类中定义新的属性(特征和技能)的过程叫做派生

子类派生出新的属性,若与父类的属性相同,则以子类的为准

两种派生方式

方式一(类调用):

# 选课系统
class OldboyPeople:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class OldboyTeacher(OldboyPeople):
    def __init__(self, name, age, gender, salary):
    	OldboyPeople.__init__(self, name, age, gender)
        self.salary = salary
    
    def change_score(self):
        print('change_score')
        
class OldboyStudent(OldboyPeople):    
    def choose_course(self, course):
        print('{self.name}选择{course}课程')
        

tea1 = OldboyTeacher('nick', 20, 'male', 20000)
print(tea1.name, tea1.age, tea1.gender, tea1.salary)

方式二(super):

# 选课系统
class OldboyPeople:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

class OldboyTeacher(OldboyPeople):
    def __init__(self, name, age, gender, salary):
    	super().__init__(name, age, gender)
        self.salary = salary
    
    def change_score(self):
        print('change_score')
        
class OldboyStudent(OldboyPeople):    
    def choose_course(self, course):
        print('{self.name}选择{course}课程')
        

tea1 = OldboyTeacher('nick', 20, 'male', 20000)
print(tea1.name, tea1.age, tea1.gender, tea1.salary)

新式类和经典类

  1. 新式类
  • 继承了object的类以及该类的子类,都是新式类
  • python3中的所有类都是新式类
  1. 经典类
  • 没有继承object的类以及该类的子类,都叫做经典类
  • 只有python2中才有经典类

菱形继承

由于在python中允许同时继承多个父类,如A(B, C, D)

如果继承关系为非菱形结构,则会按照先找B这条分支,然后再找C这条分支,最后找D这条分支直到找到我们需要的属性

如果继承关系为菱形结构,即子类的父类最后继承了同一个类,那么属性的查找方式有两种:

  • 经典类:深度优先

  • 新式类:广度优先

经典类:

新式类:

mro()方法

python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,如:

class G:
    pass

class F(G):
    pass

class C(F):
    pass

class E(G):
    pass

class B(E):
    pass

class A(B, C, D):
    pass

print(A.mro())

class D(G):
    pass

class F(G):
    pass

class C(F):
    pass

class E(G):
    pass

class B(E):
    pass

class A(B, C, D):
    pass

print(A.mro())

for i in A.mro():
    print(i)
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
<class '__main__.A'>
<class '__main__.B'>
<class '__main__.E'>
<class '__main__.C'>
<class '__main__.F'>
<class '__main__.D'>
<class '__main__.G'>
<class 'object'>
posted @ 2019-10-10 19:48  二二二二白、  阅读(131)  评论(0编辑  收藏  举报