面向对象之继承

一.继承

1.1什么是继承

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

ps:派生类是在继承父类的基础上有一些自己的属性或者技能(有和父类不一样的东西)

1.2为什么要用继承

  为了减少代码的冗余,重用已有的代码,提高重用性

1.3python中继承有何特点:

  1.子类可以遗传/重用父类的属性

  2.python中一个子类可以同时继承多个父类

  3.在继承背景下去说,python中的类分为两种:新式类,经典类

经典类和新式类:
    经典类:经典类只存在与python2中,在书写时没有继承object类,或者继承osject类的子类
    新式类:在python3中全都是新式类,在python2中继承了object的类都叫做新式类

1.4继承的基本语法

class Foo:
    pass

class Student(Foo):
    pass

基本语法:class 类名(要继承的类名):
                   

1.5继承的注意事项

  1.先抽象在继承

  2.继承一个现有的类,扩展或者修改原始的功能

ps:抽象就是将多个子类中的相同部分进行抽取,形成一个新的类

二.如何用继承关系解决类和类之间代码冗余的问题

class OldboyStudent:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex


class OldboyTeacher:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

stu1=OldboyStudent('',38,'male')
print(stu1.__dict__)

tea1=OldboyTeacher('zhang',18,'male')
print(tea1.__dict__)

class OldboyPeople:
    school = 'Oldboy'

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class OldboyStudent(OldboyPeople):
    pass
class OldboyTeacher(OldboyPeople):
    pass


stu1=OldboyStudent('',38,'male')
print(stu1.__dict__)

tea1=OldboyTeacher('zhang',18,'male')
print(tea1.__dict__)
继承解决代码冗余(继承后)

三.在子类派生出的新方法中重用父类的功能集中方式

3.1指名道姓的方式(__init__)

class OldboyPeople:
    school = 'Oldboy'

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class OldboyStudent(OldboyPeople):
    def __init__(self, name, age, sex, score=0):
        OldboyPeople.__init__(self,name,age,sex)
        self.score = score

    def choose_course(self):
        print('%s choosing course' % self.name)

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        OldboyPeople.__init__(self,name,age,sex)
        self.level=level

    def score(self,stu,num):
        stu.score=num


stu1=OldboyStudent('',38,'male')
print(stu1.__dict__)

tea1=OldboyTeacher('zhang',18,'male',10)
print(tea1.__dict__)
View Code

ps:1.该方式和继承没有任何关系
   2.访问是类的函数,没有自动传值的效果,需要几个参数就要传几个
   3.当你继承一个现有的类,并且你覆盖 了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数

3.2方式二super

  在python2中:super(自己的类名,自己的对象).你要调的父类的属性或方法

  在python3中:super().你要调的父类的属性或方法

ps:1. 严格依赖继承的mro列表
     2. 访问是绑定方法,有自动传值的效果

ps:mro列表是由类名.mro()产生的一个列表,属性的查找会严格按照这个来执行,即后面的类名一定是前一个的爹

class OldboyPeople:
    school = 'Oldboy'

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class OldboyStudent(OldboyPeople):
    def __init__(self, name, age, sex, score=0):
        super(OldboyStudent,self).__init__(name,age,sex)
        self.score = score

    

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        super().__init__(name,age,sex)
        self.level=level



stu1=OldboyStudent('',38,'male')
print(stu1.__dict__)

tea1=OldboyTeacher('zhang',18,'male',10)
print(tea1.__dict__)
super两种使用方式

四.属性查找的顺序

1.在单继承背景下的查找顺序对象->对象的类->父类->......

class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1() # obj.f1()此处会先找obj自己,然后去所属的类Bar中寻找

class Bar(Foo):
    def f1(self):
        print('Bar.f1')

obj=Bar()
obj.f2()

2.在多继承背景下的查找顺序

4.2.1如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)

class H:
    x='H'
class E:
    x='E'
class F(H):
    x='F'
class G:
    x='G'
class B(E):
    x='B'
class C(F):
    x='C'
class D(G):
    x='D'
class A(B,C,D):
    x='A'
print(A.mro())

#[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.H'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
如果一个子类继承多个分支(多个分支没有共同继承一个非object的类)

 

查找顺序是对象-->对象的类-->按照从左到右的顺序一个分支一个分支的找完

4.2.2 菱形继承

4.2.2.1新式类:广度优先,最后才去找最后的一个类

class H:
    x='H'
class E(H):
    x='E'
class F(H):
    x='F'
class G(H):
    x='G'
class B(E):
    x='B'
class C(F):
    x='C'
class D(G):
    x='D'
class A(B,C,D):
    x='A'
print(A.mro())
新式类菱形继承

4.2.2.2经典类(深度优先)深度优先查找,从左往右一个分支一个分支的查找,在第一个定级类就去寻找

ps:当出现菱形继承时,新式类先深度,当遇到共同父类时就广度

          经典类就是深度优先

原文地址:https://www.cnblogs.com/z929chongzi/p/11246974.html