面向对象——继承

面向对象——继承

什么是继承?

  • 继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类。
# 父类
class Father1:
    x = 1
    pass
class Father2:
    pass
class Father3:
    pass
# 子类
class Sub(Father1, Father2, Father3):
    pass
# 子类.__bases__ 查看父类
print(Sub.__bases__)
print(Sub.x)
# 打印结果:
# (<class '__main__.Father1'>, <class '__main__.Father2'>, <class '__main__.Father3'>)
# 1

继承的作用?

  • 继承可以减少代码的冗余
# 老师类
class OldboyTeacher:
    school = 'oldboy'
    country = 'China'

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

    # 老师修改分数
    def change_score(self):
        print(f'老师 {self.name} 正在修改分数...')


# 学生类
class OldboyStudent:
    school = 'oldboy'
    country = 'China'

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

    # 学生选择课程
    def choose_course(self):
        print(f'学生 {self.name} 正在选择课程...')


stu1 = OldboyStudent('YJG', 50, 'female')
print(stu1.school, stu1.name, stu1.age, stu1.sex)

tea1 = OldboyTeacher('tank', 17, 'male')
print(tea1.school, tea1.name, tea1.age, tea1.sex)



# 这里我们会发现上面代码会有很多重复的地方,下面我们就用继承
# 定义父类People
class People:
    school = "老男孩"
    country = "China"

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


# 老师类
class OldboyTercher(People):
    def change_score(self):
        print(f"老师{self.name}正在修改分数")


# 学生类
class OldboyStudent(People):
    def choose_course(self):
        print(f"学生{self.name}正在选择课程")


stu1 = OldboyStudent("张三", 18, "男")
print(stu1.name, stu1.age, stu1.sex)
tea1 = OldboyTercher("tank", 20, "男")
print(tea1.name, tea1.age, tea1.sex)

如何实现继承?

  • 先确认谁是子类谁是父类
  • 在定义子类时 子类名(父类名)

怎么查看子类继承的那个父类?

子类.__ bases __

注意:在python中一个子类可以继承多个父类,其他语言中一个子类只有一个父类

如何寻找继承关系?

  • 确认谁是子类
  • 确认谁是父类

在继承背景下,对象属性的查找顺序

1、先从对象自己的名称空间查找

2、对象中没有,从子类名称空间查找

3、子类名称空间没有,从父类名称空间查找,没有就报错

# 父类
class Goo:
    x = 10
    pass
# 子类
class Foo(Goo):
    x = 100
    pass
foo_obj = Foo()
foo_obj.x = 1000
print(foo_obj.x)
print('对象的名称空间: ', foo_obj.__dict__)
print('子类的名称空间: ', Foo.__dict__)
print('父类的名称空间: ', Goo.__dict__)
# 打印结果
# 对象的名称空间:  {'x': 1000}
# 子类的名称空间:  {'__module__': '__main__', 'x': 100, '__doc__': None}
# 父类的名称空间:  {'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'Goo' objects>, '__weakref__': <attribute '__weakref__' of 'Goo' objects>, '__doc__': None}

就如下图:

1574765820966

派生

  • 派生指的是子类继承父类的属性和方法,并衍生出自己独有的属性和方法,这种情况就是派生。

    需要注意的是,当子类的名字和父类相同时,会优先使用子类的名字。

# 父类
class Foo:
    def f1(self):
        print("from Foo.f1....")

    def f2(self):
        print("from Foo.f2....")
        self.f1()


# 子类
class Bar(Foo):
    def f1(self):
        print("from Bar.f1....")

    def func(self):
        print("from Bar.func....")


bar_obj = Bar()
bar_obj.f1()
bar_obj.func()
bar_obj.f2() 
# 打印结果:
# from Bar.f1....
# from Bar.func....
# from Foo.f2....
# from Bar.f1....

子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法

怎么用呢?

1、直接引用父类的__ init __为其传参,并添加子类的属性

2、通过super来指向父类的属性

​ super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间

注意:这两种方式使用哪一种都可以,但不可以混合使用

# 方式一 __init__()方法
class People:
    school = "oldboy"

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


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

    def change_score(self):
        print(f"老师{self.name}修改分数...")


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

    def choose_course(self):
        print(f"学生{self.name}选择课程...")


tea1 = OldboyTeacher("tank", 18, "男", 150000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal)
stu1 = OldboyStudent("张全蛋", 20, "男", "凤姐")
print(stu1.name, stu1.age, stu1.sex, stu1.girl)


# 方式二  super()方法
class People:
    school = "oldboy"

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


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

    def change_score(self):
        print(f"老师{self.name}修改分数...")


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

    def choose_course(self):
        print(f"学生{self.name}选择课程")


tea1 = OldboyTeacher("tank", 25, "男", 15000)
print(tea1.name, tea1.age, tea1.sex, tea1.sal)
stu1 = OldboyStudent("张全蛋", 18, "男", "凤姐")
print(stu1.name, stu1.age, stu1.sex, stu1.girl)

这里提一嘴经典类与新式类的知识(了解)

新式类

1、python2中凡是继承object的类或子孙类都是新式类

2、python3中所有的类都默认继承object

经典类

1、python2中凡是没有继承object的类都是经典类

2、python3中没有经典类

在python3中提供了一个查找新式类查找顺序的内置方法

mro():会把当前类的继承关系列出来

多继承情况下造成"钻石继承"(菱形继承)

mro查找顺序:

​ 新式类:广度优先

​ 经典类:深度优先

# 新式类:
# 这里只说新式类,博主电脑没装python2
class A(object):
    def test(self):
        print('from A')
    pass

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

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

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

class F(D, E):
    def test(self):
        print('from F')
    pass

# F-->D-->B-->E-->C-->A-->object
print(F.mro())
# 打印结果:
# [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

实在不太理解还有图

1574765137491

posted @ 2019-11-26 19:50  小小小小小小小小小白  阅读(224)  评论(1编辑  收藏  举报