继承特性

继承特性

一、什么是继承

  • 继承是一种新建类的方式,继承了一个类,类中的属性和方法就在子类中,类主要分为:父类/基类,子类/派生类

  • 新式类

  • 经典类

  • 没有继承object的类,就是经典类,python3中没有经典类,python2中才有


class A(object):
    pass

class C(object):
    pass

class B(A, C):
    pass

# 类的其他内置属性,__名字__
# 查看类的属性和方法
print(B.__dict__)

# 查看类名
print(B.__name__)

# 查看B类的父类
print(B.__bases__)

{'module': 'main', 'doc': None}
B
(<class 'main.A'>, <class 'main.C'>)

二、继承重用父类

类实例化会自动调用__init__如果类中没有,去父类中找

class Person:
    school = 'hnnu'

class Teacher(Person):
    def __init__(self, name,age,level):
        self.name = name
        self.age = age
        self.level = level

class Student(Person):
    school = 'bj'

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


stu1 = Student('zhangsan', 18, 'python')
print(stu1.school)

stu1.school = 'xxx'
print(stu1.school)

bj
xxx

三、属性的查找顺序

先找到当前的对象—>类中找--->父类中找(注意多继承)—>报错(找不到)

四、多层继承和多继承

# 多层继承

class A:
    a = 'aaa'

class B(A):
    b = 'bbb'

class C(B):
    c = 'ccc'

class D(C):
    d = 'ddd'

d = D()
print(d.a)

ddd

# 多继承
class A:
    a = 'aaa'

class B:
    a = 'bbb'

class C:
    a = 'ccc'

class D(A,B,C):
    a = 'ddd'


d = D()
print(d.a)

ddd

四、菱形问题


# 继承菱形问题: 新式类和经典类的查找顺序不一样
# 新式类的查找属性:广度优先
# 经典类:深度优先

class G():
    a = 'ggg'


class F(G):
    a = 'fff'


class E(F):
    a = 'eee'


class D(E):
    a = 'ddd'


class C(D):
    a = 'ccc'


class B(C):
    a = 'bbb'


class A(B, C, D):
    a = 'aaa'

a = A()
print(a.a)

# mro 列表,查看继承顺利列表(只在新式类中有)
print(A.mro())
print(A.__mro__)


  • 继承菱形问题在python3中显示的都是继承一个类,不是object类, 新式类和经典类的查找顺序是不一样
  • 新式类(python3中全是新式类):广度优先---从左侧开始,一直往上找,找到菱形的顶点结束(不包含菱形顶点),继续下一个继承父类往上找,找到菱形的顶点结束(不包含括菱形的顶点),最后找到菱形顶点
  • 经典类(python2中才有):深度优先搜索---从左侧开始,一直往上找,找到菱形顶点结束(包括菱形顶点),继续下一个继承父类往上找,找到菱形的顶点结束(不包含菱形顶点)

五、重用父类方法的两种方式


class Person:
    school = 'hnnu'

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

    def study(self):
        print('study...')


class Teacher(Person):
    def __init__(self, name, age, level):
        self.name = name
        self.age = age

        self.level = level


# 重用父类方法一
class Student1(Person):
    # 重用父类__init__方法
    def __init__(self, name, age, course):
        Person.__init__(self, name, age)
        self.course = course

    def study(self):
        Person.study(self)
        print(f'{self.name}学生在学习')


# 重用父类方法二
class Student2(Person):
    # 重用父类方法__init方法
    def __init__(self, name, age, course):
        # super() 会按照mro列表拿到父类对象
        # 对象来调用绑定方法,不需要传递第一个参数(self)
        super().__init__(name, age)

        # 经典类中必须这样写(py3中没有经典类),但是在python3中都用上面那种方式写
        super(Student2, self).__init__(name, age)
        self.course = course

    def study(self):
        Person.study(self)
        print(f'{self.name}学生在学习')

stu1 = Student1('web', 18, 'Python')
stu1.study()

stu2 = Student2('xiaomei', 19, 'Linux')
stu2.study()

study...
web学生在学习
study...
xiaomei学生在学习

  1. 总结,有继承关系的时候,通常用super

  2. 指名道姓的方式在什么情况下用?

    • 没有继承关系
    • 如果继承了多个父类,super是按照mro列表找,现在想指名道姓的用某个父类的某个方法,就需要指名道姓的使用
posted @ 2019-08-27 20:22  RandySun  阅读(856)  评论(0编辑  收藏  举报