继承

继承

1.什么是继承?

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

在python中,一个子类可以继承多个父类(面试题)

在其他语言中,一个子类只能继承一个父类

2.继承的作用?

减少代码的冗余

3.如何实现继承?

1)先确认呢谁是子类,谁是父类

2) 在定义类子类时,子类名(父类名)

父类
class Father1:
    pass
class Father2:
    pass
class Father3:
    pass
子类
class Sub(Father1,Father2,Father3):
    pass

# 子类。__bases__查看父亲
print(Sub.__bases__)
print(Sub.x)

4.如何寻找继承关系:

确认谁是子类

确认谁是父类

先抽象,再继承:

​ 抽取对象之间相似的部分,总结出类

​ 抽取类之间相似的部分,总结出父类

代码冗余
# 老师类
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}正在选择课程。。。')
        
解决代码冗余
# 老男孩人类
class OldboyPeople:
    school = 'oldboy'
    country = 'china'
    
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
        
# 老师类
class OldboyTeacher(OldboyPeople):
    # 老师修改分数
    def change_score(self):
        print(f'老师{self.name}正在修改分数...')

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

    

程序的执行顺序是由上而下,父类必须定义在子类的上方

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

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

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

3.子类中没有,从父类的名称空间中查找,若父类没有,则会报错

ps: 对象中添加属性的操作
    坑:并不是修改子类的属性

派生:

​ 指的是子类继承父类的属性与方法,并且派生出自己独有的属性和方法

​ 若子类中的方法名与父类的相同有先用子类的

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

    def f2(self):  # self ---> bar_obj
        print('from Foo.f2...')
        # bar_obj.f1() ---> 对象自己找 ---> Bar ---> Foo
        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()  # from Bar.f1..
# bar_obj.func()  # from Bar.func...
# bar_obj.f2()  # from Foo.f2...

# 派生后继承关系查找验证:
bar_obj = Bar()
bar_obj.f2()


结果:
from Foo.f2...
from Bar.f1..

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

子类重写父类的__ init __会导致代码更加冗余

代码冗余
# 老师类
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}正在选择课程。。。')

解决问题: 子类重用父类的属性,并派生出新的属性

​ 两种方式:

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

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

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

​ ps: 使用哪一种都可以,但不能两种方式混合使用

第一种
class OldboyPeople:
    school = 'oldboy'
    country = 'china'

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


class OldboyTeacher(OldboyPeople):
    def __init__(self, name, age, sex, sal):
        # 类调用内部的__init__只是普通的函数
        OldboyPeople.__init__(self, name, age, sex)
        self.sal = sal

    def change_score(self):
        print(f'老师{self.name}对成绩做了修改!')


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

    def choose_course(self):
        print(f'学生{self.name}进行选课!')


teacher = OldboyTeacher('tank', 28, 'female', 120000)
print(teacher.name, teacher.sex, teacher.age, teacher.sal)

    
第二种
class OldboyPeople:
    school = 'oldboy'
    country = 'china'

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


class OldboyTeacher(OldboyPeople):
    def __init__(self, name, age, sex, sal):
        # 类调用内部的__init__只是普通的函数
        super().__init__(name, age, sex)
        self.sal = sal

    def change_score(self):
        print(f'老师{self.name}对成绩做了修改!')


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

    def choose_course(self):
        print(f'学生{self.name}进行选课!')


teacher = OldboyTeacher('tank', 28, 'female', 120000)
print(teacher.name, teacher.sex, teacher.age, teacher.sal)

经典类与新式类:

​ 新式类:

​ 1.凡是继承object的类或子孙类都是新式类

​ 2.在python3中所有的类都默认继承object

​ 经典类:

​ 1.在python2中才会有经典类与新式类之分

​ 2.在python2中,凡是没有继承object的类,都是经典类

# class User(object):
#     pass
python3中所有的类都是继承object

class User:
    x = 10
    pass


class Sub(User):
    pass


print(User.__dict__)


{'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}


python2中
#!/usr/bin/u/ubv/a python
# _*_ coding:utf8 _*_


class User(object):
    x = 10
    pass


class Sub(User):
    pass


print(User.__dict__)

{'__dict__': <attribute '__dict__' of 'User' objects>, 'x': 10, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}


#!/usr/bin/u/ubv/a python
# _*_ coding:utf8 _*_


class User():
    x = 10
    pass


class Sub(User):
    pass


{'x': 10, '__module__': '__main__', '__doc__': None}

调用mro返回的是一个继承序列:

​ super的继承顺序严格遵循mro继承序列

多继承的情况下:从左至右

在python3中提供了一个查找新式类查找顺序的内置方法,mro():会把当前类的继承关系列出来

class A:
    def test(self):
        print('from A.test')
        super().test()


class B:
    def test(self):
        print('from B.test')


class C(A, B):
    pass

print(C.mro())

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

c = C()
c.test()

from A.test
from B.test

多继承情况下造成‘钻石继承’

mro的查找顺序:

新式类:

​ 广度优先

经典类:

​ 深度优化

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())
obj = F()
obj.test()


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

菱形继承下的经典类和新式类的详解:
https://blog.csdn.net/XiaoMaGe1996/article/details/80828864
posted @ 2019-11-26 19:13  godlover  阅读(88)  评论(0编辑  收藏  举报