继承与派生

一:认识继承

什么是继承?

  继承是一种创建新类的方式,创建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生或子类

  子类会遗传父类的属性,从而解决代码重用性的问题

python中的继承分为单继承和多继承
class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass
查看继承
>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
新式类和经典类

在python3中所有的类都是新式类

在Python2中所有的没有显示的继承object的类及其子类都是经典类

在Python2中所有的显示的继承object的类及其子类都是新式类

注意:如果没有指定基类,在python3中会默认继承object类,object类是所有python类的基类

二:继承与抽象

  继承描述的是子类与父类之间的关系,具体一种什么样的关系,需要先抽象,找出关系,才能来继承

  抽象:即把对象相似的特征抽取出来

  定义两个类,学生类和老师类,其共同点在于他们都有名字和年龄、性别,把这一部分抽取出来,组成一个类:人类,

  人类和学生类、老师类的关系可以很清楚的看到:学生类和老师类继承人类

  于是:继承就是基于抽象的结果,通过编程语言去实现它

三:继承与重用

  在子类派生出的新方法中重用父类的功能
  方式一:指名道姓的调用,该方法与继承实际没有关系

class OldboyPeople:
    school = "oldboy"
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex =sex

class Student(OldboyPeople):
    def choose(self):
        print("stu %s choose course..."%self.name)

class Teacher(OldboyPeople):
    def __init__(self,name,age,sex,salary,level):
        OldboyPeople.__init__(Teacher,name,age,sex)
        self.salary =salary
        self.level =level
    def change_score(self):
        print("tec %s change score..."%self.name)

t2 = Teacher("alex",38,"male",3.1,9)
t3 = Teacher("egon",18,"male",33,10)

print(t2.school,t2.name,t2.level,t2.salary,t2.age)
print(t3.school,t3.name,t3.level,t3.salary,t3.age)

  方式二:super()调用,严格依赖于继承,super()的返回值是一个特殊的对象,该对象专门用来调用父类当中的属性

class OldboyPeople:
    school = "oldboy"
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex =sex

class Student(OldboyPeople):
    def choose(self):
        print("stu %s choose course..."%self.name)

class Teacher(OldboyPeople):
    def __init__(self,name,age,sex,salary,level):
        super().__init__(name,age,sex)
        self.salary =salary
        self.level =level
    def change_score(self):
        print("tec %s change score..."%self.name)

t2 = Teacher("alex",38,"male",3.1,9)
t3 = Teacher("egon",18,"male",33,10)

print(t2.school,t2.name,t2.level,t2.salary,t2.age)
print(t3.school,t3.name,t3.level,t3.salary,t3.age)

  提示:用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大生了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.

四:派生

  子类同样也可以添加自己的新属性或者重新定义这些属性(这样做不会对父类产生影响),需要注意的是:如果子类定义的属性名和父类同名,那么在调用新增的属性时,以自己的为准

class Foo:
    def __int__(self):
        pass

    def f1(self):
        self.f1()
        print("from foo")

class Bar(Foo):
    def __int__(self):
        pass

    def f1(self):
        print("from bar")

b1 = Bar()
b1.f1()

  在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值

class Foo:
    def __int__(self):
        pass

    def f1(self):
        print("from foo")

class Bar(Foo):
    def __int__(self):
        pass

    def f1(self):
        Foo.f1(Bar)
        super().f1()
        print("from bar")

b1 = Bar()
b1.f1()

# from foo
# from foo
# from bar

五:继承顺序

1、新式类
继承object的类以及他的子类都是新式类
没有继承object的类以及他的子类都是经典类

非菱形背景下属性查找:
  不区分新式类还是经典类,从左至右一个个查找到底

菱形背景下属性查找
经典类:深度优先


新式类:广度优先

class A:
    def test(self):
        super().test()
class B:
    def test(self):
        print('from B')
class C(A,B):
    pass

c=C()
c.test() #打印结果:from B

print(C.mro())
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
A没有继承B,但是A内super会基于C.mro()继续往后找

posted @ 2018-04-12 15:25  Leslie-x  阅读(173)  评论(0编辑  收藏  举报