• python面向对象进阶-继承、多态


    继承

    python面向对象的继承指的是多个类之间的所属关系,及子类默认继承父类的所有属性和方法
    1. #父类A
    2. class A(object):
    3.     def __init__(self):
    4.         self.num = 1
    5.     #定义成员函数:方法
    6.     def info_print(self):
    7.         print(self.num)
    8. #子类,继承父类
    9. class B(A):
    10.     pass
    # 3.创建对象验证结论
    1. result = B()
    2. result.info_print() #1
    在python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。

    单继承

    1. 单个子类继承单个父类所有属性和方法
    2. #1.师傅类,属性和方法
    3. class Master(object):
    4.     def __init__(self):
    5.         self.kongfu = '【古法煎饼果子配方】'
    6.     def make_cake(self):
    7.         print(f'运用{self.kongfu}制作煎饼果子')
    8. #2.定义徒弟类
    9. class Prentice(Master):
    10.     pass
    11. #创建对象daqiu
    12. daqiu = Prentice()
    13. #4.对象访问实例属性
    14. print(daqiu.kongfu)
    15. daqiu.make_cake()

    多继承

    所谓多继承意思就是一个类 同时继承了多个父类
    1. #1.师傅类,属性和方法
    2. class Master(object):
    3.     def __init__(self):
    4.         self.kongfu = '【古法煎饼果子配方】'
    5.     def make_cake(self):
    6.         print(f'运用{self.kongfu}制作煎饼果子')
    7. #添加school类
    8. class School(object):
    9.     def __init__(self):
    10.         self.kongfu = '[黑马煎饼果子配方]'
    11.     def make_cake(self):
    12.         print(f'运用{self.kongfu}制作煎饼果子')
    #2.定义徒弟类,按调用顺序来作为第一个父类,显示同名函数和属性
    1. #继承多个父类
    2. class Prentice(Master,School):
    3.     pass
    4. #用徒弟类,继承师傅类
    5. daqiu = Prentice()
    6. print(daqiu.kongfu)
    7. daqiu.make_cake()
    注意:当一个类有多个父类的时候, 默认使用第一个父类的同名属性和方法(不是按定义顺序排序,而是调用顺序)
    子类重写父类同名方法和属性
    以上代码修改子类,重写属性和函数即可
    #2.定义徒弟类,按调用顺序来作为第一个父类,显示同名函数和属性
    1. #继承多个父类  添加和父类同名的属性和方法
    2. class Prentice(Master,School):
    3.     def __init__(self):
    4.         self.kongfu = '[独创煎饼果子技术]'
    5.     def make_cake(self):
    6.         print(f'运用{self.kongfu}制作煎饼果子')

    注意:如果子类和父类拥有同名属性,子类创建对象调用属性和方法的时候, 调用到的是子类里面的同名属性和方法
    通过_mro_显示继承层级顺序
    print(子类.__mro__)
    显示了子类的继承关系
    子类调用父类的同名方法
    1. #1.师傅类,属性和方法
    2. class Master(object):
    3.     def __init__(self):
    4.         self.kongfu = '【古法煎饼果子配方】'
    5.     def make_cake(self):
    6.         print(f'运用{self.kongfu}制作煎饼果子')
    7. #添加school类
    8. class School(object):
    9.     def __init__(self):
    10.         self.kongfu = '[黑马煎饼果子配方]'
    11.     def make_cake(self):
    12.         print(f'运用{self.kongfu}制作煎饼果子')
    #2.定义徒弟类,按调用顺序来作为第一个父类,显示同名函数和属性
    1. #继承多个父类  添加和父类同名的属性和方法
    2. class Prentice(Master,School):
    3.     def __init__(self):
    4.         self.kongfu = '[独创煎饼果子技术]'
    5.     def make_cake(self):
    6.         self.__init__()
    7.         print(f'运用{self.kongfu}制作煎饼果子')
    8.     #子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    9.     def make_master_cake(self):
    10.         #父类类名.函数()
    11.         #再次调用初始化的原因:这里想要调用父类的同名方法和属性,
    12.         # 属性在init初始化位置,所以需要再次调用init
    13.         Master.__init__(self)
    14.         Master.make_cake(self)
    15.     def make_school_cake(self):
    16.         School.__init__(self)
    17.         School.make_cake(self)
    18. #用徒弟类创建对象,调用实例属性和方法
    19. daqiu = Prentice()
    20. daqiu.make_cake()
    21. daqiu.make_master_cake()
    22. daqiu.make_school_cake()
    23. daqiu.make_cake()
    多层继承
    1. #1.师傅类,属性和方法
    2. class Master(object):
    3. def __init__(self):
    4. self.kongfu = '【古法煎饼果子配方】'
    5. def make_cake(self):
    6. print(f'运用{self.kongfu}制作煎饼果子')
    7. #添加school类
    8. class School(object):
    9. def __init__(self):
    10. self.kongfu = '[黑马煎饼果子配方]'
    11. def make_cake(self):
    12. print(f'运用{self.kongfu}制作煎饼果子')
    13. #2.定义徒弟类,按调用顺序来作为第一个父类,显示同名函数和属性
    14. #继承多个父类 添加和父类同名的属性和方法
    15. class Prentice(Master,School):
    16. def __init__(self):
    17. self.kongfu = '[独创煎饼果子技术]'
    18. def make_cake(self):
    19. self.__init__()
    20. print(f'运用{self.kongfu}制作煎饼果子')
    21. #子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    22. def make_master_cake(self):
    23. #父类类名.函数()
    24. #再次调用初始化的原因:这里想要调用父类的同名方法和属性,
    25. # 属性在init初始化位置,所以需要再次调用init
    26. Master.__init__(self)
    27. Master.make_cake(self)
    28. def make_school_cake(self):
    29. School.__init__(self)
    30. School.make_cake(self)
    31. #1.创建Tusun,用这个类创建对象;2.用这个对象调用父类的属性或方法看是否能成功。
    32. class Tusun(Prentice):
    33. pass
    34. xiaoqiu = Tusun()
    35. xiaoqiu.make_cake()
    36. xiaoqiu.make_master_cake()
    37. xiaoqiu.make_school_cake()

    使用super()调用父类方法
    当需要一次性调用父类:类一、类二的时候可以使用super()函数
    作用:减少代码冗余,提高扩展性
    带参与不带参数super()写法
    1. #1.师傅类,属性和方法
    2. class Master(object):
    3.     def __init__(self):
    4.         self.kongfu = '【古法煎饼果子配方】'
    5.     def make_cake(self):
    6.         print(f'运用{self.kongfu}制作煎饼果子')
    7. #添加school类
    8. class School(Master):
    9.     def __init__(self):
    10.         self.kongfu = '[黑马煎饼果子配方]'
    11.     def make_cake(self):
    12.         print(f'运用{self.kongfu}制作煎饼果子')
    13.         
    14.         #2.1 super()带参数写法
    15.         # super(School, self).__init__()
    16.         # super(School, self).make_cake()
    17.         #2.2 无参数的super()
    18.         super().__init__()
    19.         super().make_cake()
    20. #2.定义徒弟类,按调用顺序来作为第一个父类,显示同名函数和属性
    21. #继承多个父类  添加和父类同名的属性和方法
    22. class Prentice(School):
    23.     def __init__(self):
    24.         self.kongfu = '[独创煎饼果子技术]'
    25.     def make_cake(self):
    26.         self.__init__()
    27.         print(f'运用{self.kongfu}制作煎饼果子')
    28.     #子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
    29.     def make_master_cake(self):
    30.         #父类类名.函数()
    31.         #再次调用初始化的原因:这里想要调用父类的同名方法和属性,
    32.         # 属性在init初始化位置,所以需要再次调用init
    33.         Master.__init__(self)
    34.         Master.make_cake(self)
    35.     def make_school_cake(self):
    36.         School.__init__(self)
    37.         School.make_cake(self)

    #需求:一次性调用父类Shool Master的方法
    1. #先定义一个类
    2.     def make_old_cake(self):
    3.         #方法一
    4.         #2.1 super(当前类明,self).函数()
    5.         # super(Prentice, self).__init__()
    6.         # super(Prentice, self).make_cake()
    7.         #2.2 无参数super()
    8.         super().__init__()
    9.         super().make_cake()
    10. xiaoqiu = Prentice()
    11. xiaoqiu.make_old_cake()

    私有属性
    当想保留自己的密码不继承给别人时,就可以设置私有属性。
    定义私有属性和方法
    在属性名和方法名前加两条下划线 __ 即可
    如:
    1. #定义私有属性:在属性名前加两条下划线__即可
    2.     self.__money = 2000000
    3. #定义私有方法: 在方法名前加两条下划线__即可
    4. def __info_print(self):
    5.     print("这是私有方法")
    获取和修改私有属性值
    在python中一般定义函数名get_xx用来获取私有属性,定义set_xx用来修改私有属性值。
    1. #定义函数,获取私有属性值get_xx
    2. def get_money(self):
    3.     return self.__money
    4. #定义函数:修改私有属性值 set_xx
    5. def set_money(self):
    6.     self.__money = 5000
    7. #调用验证
    8. xiaoqiu = Tusun()
    9. print(xiaoqiu.get_money())
    10. xiaoqiu.set_money()
    11. print(xiaoqiu.get_money())
    继承总结:
    特点:
        子类默认拥有父类的所有属性和方法
        子类重写父类同名方法和属性
        子类调用父类同名方法和属性
    super()方法快速调用父类方法
    私有权限
        不能继承给子类的属性和方法需要添加私有权限
        
    私有权限语法
    1. class 类名():
    2.     #私有属性
    3.     __属性名 = 值
    4.     #私有方法
    5.     def __函数名(self):
    6.         代码

    面向对象—多态

    多态:

        指的是一类事物有多种形态。(一个抽象类有多个子类,因而多态的概念依赖于继承)。
    定义:
        多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
    好处:
        调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
    实现步骤:
        定义父类,并提供公共方法
        定义子类,并重写父类方法
        传递子类对象给调用者,可以看到不同子类执行效果不同
    案例
    1. #警务人员和警犬一起工作,警犬2分钟:
    2. # 追击敌人和毒品追查,携带不同的警犬,执行不同的工作
    3. #1.定义狗的父类,子类重写父类方法:
    4. class Dog(object):
    5.     def work(self):
    6.         pass
    7. #2.定义2个狗类表示不同的警犬,子类重写父类方法:
    8. class ArmDog(Dog):
    9.     def work(self):
    10.         print("追击敌人...")
    11. class DrugDog(Dog):
    12.     def work(self):
    13.         print("追查毒品...")
    14. #定义人类
    15. class Person(object):
    16.     def work_with_dog(self,dog):
    17.         dog.work()
    18. #3.创建对象·调用不同的功能传入不同的对象,观察执行的结果
    19. ad = ArmDog()
    20. dd = DrugDog()
    21. daqiu = Person()
    22. daqiu.work_with_dog(ad) #追击敌人...
    23. daqiu.work_with_dog(dd) #追查毒品...
    类属性和实例属性
    类属性
    设置和访问类属性
        类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有。
        类属性可以使用类对象或实例对象访问。
    案例:
    1. #1.定义类,定义类属性
    2. class Dog(object):
    3.     tooth = 10
    4. #2.创建对象
    5. wangcai = Dog()
    6. xiaohei = Dog()
    7. #3.使用类和对象访问类属性
    8. print(Dog.tooth)    #10
    9. print(wangcai.tooth) #10
    10. print(xiaohei.tooth) #10
    类属性优点:
        记录的某项数据始终保持一致时,则定义类属性。
         实例属性 要求 每个对象为其 单独开辟一份内存空间来记录数据。
         类属性 为全类共有,仅占一份内存,更加节省内存空间。
    修改类属性
        
    1. class Dog(object):
    2.     tooth = 10
    3. wangcai = Dog()
    4. xiaohei = Dog()
    5. #1. 类  类.类属性 = 值
    6. # Dog.tooth = 20
    7. # print(Dog.tooth)
    8. #
    9. # #使用对象获取属性值
    10. # print(wangcai.tooth)
    11. # print(xiaohei.tooth)
    12. #2.测试通过对象修改类属性
    13. wangcai.tooth = 200     #实际是为wangcai添加了实例属性
    14. print(Dog.tooth) #10
    15. print(wangcai.tooth) #200
    16. print(xiaohei.tooth) #10
    注意:
        类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。

    类方法和静态方法

    类方法特点
        需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。
    类方法使用场景
        当方法中需要使用类对象(如访问私有类属性等)时,定义类放方法
        类方法一般和类属性配合使用
    1. #1.定义类:私有类属性,类方法获取这个私有类属性
    2. class Dog(object):
    3.     __tooth = 10
    4.     #定义类方法
    5.     @classmethod
    6.     def get_tooth(cls):
    7.         return cls.__tooth
    8. #2.创建对象,调用类方法
    9. wangcai = Dog()
    10. result = wangcai.get_tooth()
    11. print(result)   #10
    静态方法特点
        需要通过装饰器@staticmethod来进行装饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。
     静态方法 也能够通过 实例对象和类对象访问。
    使用场景
        当方法中既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性、类方法、创建实例时等)时,就定义类方法。
        取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗。
    1. #1.定义类,定义静态方法
    2. class Dog(object):
    3.     @staticmethod
    4.     def info_print():
    5.         print("这是一个静态方法")
    6. #创建对象
    7. wangcai = Dog()
    8. #3. 调用静态方法:类 和 对象
    9. wangcai.info_print()
    10. Dog.info_print()
    11. 总结:
    12. 类方法语法:
    13. @classmethod
    14. def类名():
    15.     代码
    16. 静态方法语法:
    17. @staticmethod
    18. def类名():
    19.     代码
  • 相关阅读:
    数据结构栈和队列
    计算机网络——传输层
    Codeforces 1255B. Fridge Lockers
    构建未来交通:香橙派OPI Airpro上的智能交通监管系统
    c#利用Chart 画图
    Python最基础的五个部分代码,零基础也能轻松看懂。
    算法记录 & 牛客网 & leetcode刷题记录
    CMMI5认证哪些企业可以申请
    SAMBA配置
    springboot 如何解决循环依赖
  • 原文地址:https://blog.csdn.net/gyqailxj/article/details/128088615