学习python的day13之面向对象-继承

面向对象-继承

1.体验继承

python面向对象的继承指多个类之间的从属关系,即子类默认及继承父类的所有属性和方法,具体如下:

#父类
class A(object):
    def __init__(self):
        self.num = 1
    def info_print(self):
        print(self.num)

#子类
class B(A):
    pass

redult = B()
redult.info_print()

'''
输出:
1
'''

在python中,所有类默认继承object类,object类是顶级类或基类,其他字类叫派生类

2.单继承

故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的煎饼果子技术。师傅要把这套技术传授给徒弟。

分析:要有两个类(师傅类、徒弟类),徒弟类继承师傅类

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master):
    pass
tuer = Prentice()
tuer.make_cake()
'''
输出:
使用独门绝技制作煎饼果子
'''

3.多继承

故事推进:tuer继承师傅的独门绝技后,还想去学校学习更多的技术

多继承:所谓多继承就是一个类同时继承多个父类

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    pass
tuer = Prentice()
tuer.make_cake()
'''
输出:
使用独门绝技制作煎饼果子
'''

结论:如果一个类同时继承多个父类,优先继承第一个父类的同名属性和方法

4.子类重写父类同名属性和方法

故事:徒弟掌握师傅和学校的技术后,自己潜心研究出了自己的独门秘方

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
tuer = Prentice()
tuer.make_cake()
'''
输出:
使用自创秘方制作煎饼果子
'''

结论:如果子类和父类拥有同名方法和属性,子类创建对象时调用属性和方法,调用到的是子类里面的同名属性和方法

5.拓展:__mro__   子类继承的父类以及继承顺序

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
tuer = Prentice()
tuer.make_cake()
print(Prentice.__mro__)
'''
输出:
使用自创秘方制作煎饼果子
使用自创秘方制作煎饼果子
(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
'''

6.子类调用父类的同名属性和方法

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')

    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)
tuer =Prentice()
tuer.make_cake()
tuer.Master_make_cake()
tuer.School_make_cake()
'''
输出:
使用自创秘方制作煎饼果子
使用独门绝技制作煎饼果子
使用新式秘方制作煎饼果子
'''

7.多层继承

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')

    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)
class Tusun(Prentice):
    pass
tuer =Tusun()
tuer.make_cake()
tuer.Master_make_cake()
tuer.School_make_cake()
'''
输出:
使用自创秘方制作煎饼果子
使用独门绝技制作煎饼果子
使用新式秘方制作煎饼果子
'''

 8.super()调用父类方法

带参数写法

super(当前类名,self).函数()

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(Master):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')

    #在这里调用super方法, 才能调用Master父类里的方法和属性
    def make_cake(self):
        super(School, self).__init__()
        super(School, self).make_cake()

class Prentice(School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')

    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)

    def make_waht_cake(self):
        super(Prentice, self).__init__()
        super(Prentice, self).make_cake()

tuer =Prentice()
tuer.make_waht_cake()
tuer.make_cake()
'''
输出:
使用独门绝技制作煎饼果子
使用自创秘方制作煎饼果子
'''

无参数写法

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(Master):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')

    #在这里调用super方法, 才能调用Master父类里的方法和属性
    def make_cake(self):
        super().__init__()
        super().make_cake()

class Prentice(School):
    def __init__(self):
        self.mifang = '自创秘方'
    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')

    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)

    def make_waht_cake(self):
        super().__init__()
        super().make_cake()

tuer =Prentice()
tuer.make_waht_cake()
tuer.make_cake()
'''
输出:
使用独门绝技制作煎饼果子
使用自创秘方制作煎饼果子
'''

注意:使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用。

9.私有权限

9.1定义私有属性和方法

在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性和方法不继承给子类。

设置私有权限的方法:在属性名和方法名前面加两个_

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
        self.__caichan = '2个亿'
    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')


    def __caichan(self):
        print('这是私有方法')


    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)
class Tusun(Prentice):
    pass
tuer =Tusun()
# print(tuer.caichan)
#print(tuer.__caichan)
# tuer.caichan()
# tuer.__caichan()

四个调用都会报错,因为父类不能将私有属性和方法继承给子类

9.2获取和修改私有属性值

在python中,一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值

class Master(object):
    def __init__(self):
        self.mifang = '独门绝技'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class School(object):
    def __init__(self):
        self.mifang = '新式秘方'
    def make_cake(self):
        print(f'使用{self.mifang}制作煎饼果子')
class Prentice(Master,School):
    def __init__(self):
        self.mifang = '自创秘方'
        self.__caichan = 200000

    def __caichan(self):
        print('这是私有方法')

    # 获取私有属性
    def get_caichan(self):
        return self.__caichan

    #修改私有属性
    def set_caichan(self):
        self.__caichan = 50000

    def make_cake(self):
        # 再次调用初始化的原因:这里想要调用自己的同名属性和方法,但属性在其他类被init初始化位置,所以需要再次调用
        self.__init__()
        print(f'使用{self.mifang}制作煎饼果子')

    #子类调用父类的同名属性和方法:把父类的同名属性和方法再次封装
    def Master_make_cake(self):
        #再次调用初始化的原因:这里想要调用父类的同名属性和方法,属性在子类被init初始化位置,所以需要再次调用
        Master.__init__(self)
        Master.make_cake(self)
    def School_make_cake(self):
        School.__init__(self)
        School.make_cake(self)
class Tusun(Prentice):
    pass
tuer =Tusun()
print(tuer.get_caichan())
tuer.set_caichan()
print(tuer.get_caichan())
'''
输出:
200000
50000
'''

获取和修改私有属性不一定是get_xx和set_xx,这只是工作习惯

 

总结

继承的特点

  子类默认拥有父类的所有属性和方法

  子类重写分类同名属性和方法  

  子类调用父类同名属性和方法

super()快速调用父类方法

私有权限

  不能继承给子类的属性和方法需要添加私有权限

  语法:

    class 类名()

      #私有属性

      __属性名 = 值

      #私有方法

      def  __函数名(self):

        代码

 

posted @ 2020-11-07 00:21  as_scheduled  阅读(103)  评论(0编辑  收藏  举报