29、继承

一、继承

1.1、什么是继承

  继承是一种创建新类的方式,新建的类可以称为子类或者派生类,父类可以称为基类或者超类,子类会遗传父类
1.2、Python中的继承

  python中支持多继承关系,一个子类可以继承一个或者多个父类

class Parent1(object):
    x=1111
class Parent2(object):
    pass
class Sub1(Parent1):                                        # 单继承
    pass
class Sub2(Parent1,Parent2):                            # 多继承
    pass
print(Sub1.__bases__)
print(Sub2.__bases__)
print(Sub1.x)

1.3、python2以及python3中继承的区别

  python2

    新类式:继承可了object类的子类

    经典式:没有继承object类的子类

  python3

    python3中只有新类式,没有继承任何类的都会默认继承object类
1.4、python的多继承

  优点:

    子类可以继承多个父类,最大程度的限制重用代码
  缺点:

    1、违背人的思维习惯,继承表达的是一种什么是什么的关系

    2、代码可读性变差

    3、不建议使用多继承,有肯能会引发菱形问题,扩展性变差
  注:

    如果不可避免的需要使用到多个父类的属性,应该使用mixins

1.5、为什么要使用继承

  解决类与类之间的代码冗余问题

1.6、怎么实现继承

  当子类需要的代码都在父类中时,可以直接引用

  当子类需要的代码只有部分在父类时,编写类,再指名道姓的从父类中引用代码例如:

  def __init__(self, name, age, sex, salary, level):               类

  OldboyPeople.__init__(self,name,age, sex)                    

class OldboyPeople:                                    #通用的父类代码
    school = 'OLDBOY'
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

class Student(OldboyPeople):                       #子类代码和父类代码一致,直接从父类代码中引用
    def choose_course(self):
        print('学生%s 正在选课' % self.name)
stu_obj = Student('lili', 18, 'female')
stu_obj.choose_course()

class Teacher(OldboyPeople):                      #子类代码中只有部分功能在父类中     老师的空对象,'egon',18,'male',3000,10    类中的数据要写全
    def __init__(self, name, age, sex, salary, level):                
    
# 指名道姓地跟父类OldboyPeople去要__init__ OldboyPeople.__init__(self,name,age, sex) self.salary = salary self.level = level def score(self): print('老师 %s 正在给学生打分' % self.name) tea_obj=Teacher('egon',18,'male',3000,10) tea_obj.score()

二、继承属性的查找

2.1、有了继承关系之后,对象在查找属性时,会先从自身__dict__里面找,如果没有回去子类中查找,最后到父类中

  例题一:子类中没有找到,在父类中找到,父类的函数下子类和父类中都有,会直接先从子类中读取  

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

    def f2(self):
        print('Foo.f2')
        self.f1() # obj.f1()

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

obj=Bar()
obj.f2()                           #Foo.f2    Foo.f1

3.2、子类中找不到的情况下,在父类中找到了,接着父类的函数会直接指向子类,如果要强行指向父类中,需要指明道姓的调用父类函数:Foo.f1(self)

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

    def f2(self):
        print('Foo.f2')
        Foo.f1(self) # 调用当前类中的f1

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

obj=Bar()
obj.f2()

# Foo.f2
# Foo.f1

3.3、从父类调用时,遇到隐藏属性的类,名字将会变形,但是对外不对内,所以自找到父类中的函数

class Foo:
    def __f1(self): # _Foo__f1
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1() # self._Foo__f1,# 调用当前类中的f1

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

obj=Bar()
obj.f2()

# Foo.f2
# Foo.f1

四、多继承关系带来的菱形问题

4.1、菱形问题以及MRO的介绍

  菱形问题指的是有多个父类,父类最终又指向同一个父类

  MRO:指的是类的对象访问属性的查找顺序是根据MRO的显示

4.2、查找顺序

  非菱形:

    按照子类的父类从左到右的顺序,一个分支一个分支的找下去,

  菱形:

    经典型:深度优先,每一个分支找到底,直到最终的父类,第二个分支将不会找最终的父类

    新类型:广度优先,最后一个分支才会找到最终的父类,其余的父类都会直接跳过

class G: # 在python2中,未继承object的类及其子类,都是经典类
# def test(self):
# print('from G')
pass

class E(G):
# def test(self):
# print('from E')
pass

class F(G):
def test(self):
print('from F')

class B(E):
# def test(self):
# print('from B')
pass

class C(F):
def test(self):
print('from C')

class D(G):
def test(self):
print('from D')

class A(B,C,D):
# def test(self):
# print('from A')
pass

# 新式类
# print(A.mro()) # A->B->E->C->F->D->G->object

# 经典类:A->B->E->G->C->F->D
obj = A()
obj.test() #

4.3、总结

  多继承要不要用?

  要用,但是需要规避几个问题

  1.继承结构不要过于复杂

  2.推荐使用mixins机制,在多继承的背景下满足什么是什么的关系

猜你喜欢

转载自www.cnblogs.com/jingpeng/p/12669830.html
29