python学习第25天面向对象的三大特征之继承

一、什么是继承

在程序中继承是一种新建子类的方式,新创建的类称之为子类\派生类,被继承的类称之为父类\基类\超类。
继承描述的是一种遗传关系,子类可以重用父类的属性

 

二、为何用继承

    减少类与类之间代码冗余的问题

三,如何用继承

先抽象再继承

1、python中类的继承分为:单继承和多继承

class ParentClass1: #定义父类
    pass

class ParentClass2: #定义父类
    pass

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

class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
    pass

2、查看继承

>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

3、经典类与新式类

1.只有在python2中才分新式类和经典类,python3中统一都是新式类
2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类
#关于新式类与经典类的区别,我们稍后讨论

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

4、新式类与经典类在属性查找中的区别

(1)单继承:

在单继承背景下,无论是新式类还是经典类属性查找顺序都一样,都要遵循   对象——》子类——》父类

# 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()

 

(2)多继承:

 在多继承背景下,如果一个子类继承了多个分支,但是多个分支没有汇聚到一个非object类(非菱形继承),无论是新式类还是经典类属性查找顺序都一样:
 会按照从左到右的顺序一个分支一个分支的查找下去

class E:
    # xxx='E'
    pass

class F:
    # xxx='F'
    pass

class B(E):
    # xxx='B'
    pass

class C(F):
    # xxx='C'
    pass

class D:
    # xxx='D'
    pass

class A(B,C,D):
    # xxx='A'
    pass

obj=A()
# obj.xxx=111
# print(obj.xxx)

print(A.mro())

 [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]

在多继承背景下,如果一个子类继承了多个分支,但是多个分支最终汇聚到一个非object类(菱形继承问题)
# 新式类:广度优先查找:obj->A->B->E->C->F->D->G->object
# 经典类:深度优先查找:obj->A->B->E->G->C->F->D

 

 class G:
#     xxx='G'
#
# class E(G):
#     xxx='E'
#     pass
#
# class F(G):
#     xxx='F'
#     pass
#
# class B(E):
#     xxx='B'
#     pass
#
# class C(F):
#     xxx='C'
#     pass
#
# class D(G):
#     xxx='D'
#     pass
#
# class A(B,C,D):
#     xxx='A'
#     pass
#
#
# print(A.mro())

[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]

 PS:obj.mro能查看obj的属性查找顺序

 5、在子类派生出的新功能中如何重用父类的功能:

(1)指名道姓地访问某一个类中的函数,与继承无关

class OldboyPeople:
    school = 'Oldboy'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender                         
# class OldboyTeacher(OldboyPeople):
#     #            tea, 'egon', 18, 'male', 10, 3000
#     def __init__(self, name, age, gender,level,salary):
#         OldboyPeople.__init__(self, name, age, gender)
#         self.level=level
#         self.salary=salary

## tea=OldboyTeacher('egon',18,'male',10,3000) #__init___(tea,'egon',18,'male',10,3000)
# print(tea.__dict__)

(2)super(OldboyTeacher,self),在python3中super可以不传参数,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中属性,

# 强调:super会严格参照类的mro列表依次查找属性

# class OldboyTeacher(OldboyPeople):
#     #            tea, 'egon', 18, 'male', 10, 3000
#     def __init__(self, name, age, gender,level,salary):
#         super().__init__(name, age, gender)
#
#         self.level=level
#         self.salary=salary
#
# tea=OldboyTeacher('egon',18,'male',10,3000) #__init___(tea,'egon',18,'male',10,3000)
# print(tea.__dict__)

 

posted @ 2018-10-23 17:33  凌、云  阅读(161)  评论(0编辑  收藏  举报