• 🍔类的派生


    一.什么是派生

    • 子类中新定义的属性的这个过程就叫做派生
    • 注意 : 当子类在使用派生属性的时候始终以自己的属性为准
    • 父类----->称为基类或者超类
    • 子类----->称为派生类
    class Animal:              # 父类(基类)
        def run(self):
            print("奔跑")
        
        def eat(self):
            print("吃东西")
            
    class Duck(Animal):        # 子类(派生类)
        bread = "可爱鸭"        # 派生属性(品种)
        
        def speak(self):       # 派生方法(说话)
            print("嘎嘎嘎")
    

    二.派生类中使用父类的属性和方法

    1.方式一 : 直接使用 self.[属性或方法] 来调用

    • 存在的问题 : 如果子类与父类中有相同的属性或方法, 那么就无法使用父类中的属性或方法 (因为优先使用自己的)
    • 也有可能产生递归调用
    当父类与派生类中的属性和方法不重复时 (没有问题)
    class Animal:
        def run(self):
            print("奔跑(Animal)")
    
        def eat(self):
            print("吃东西(Animal)")
    
    class Duck(Animal):
        bread = "可爱鸭(Duck)"
    
        def speak(self):
            self.eat()            # 调用父类中的 "eat()" 方法
            print("嘎嘎嘎(Duck)")
    
    duck1 = Duck()
    duck1.speak()
    '''输出
    吃东西(Animal)
    嘎嘎嘎(Duck)
    '''
    
    当派生类中也存在相同方法 "eat()" 的时候, (优先调用自己的方法)
    class Animal:
        def run(self):
            print("奔跑(Animal)")
    
        def eat(self):
            print("吃东西(Animal)")
    
    class Duck(Animal):
        bread = "可爱鸭(Duck)"
    
        def eat(self):           # 子类中存在 "eat()" 方法
           # self.eat()          # 这种情况为递归调用,会超过最大深度,报错
            print("吃东西(Duck)")
            
        def speak(self):
            self.eat()            # 想调用父类中的 "eat()" 方法
            print("嘎嘎嘎(Duck)")
    
    duck1 = Duck()
    duck1.speak()
    '''输出
    吃东西(Duck)
    嘎嘎嘎(Duck)
    '''
    

    2.方式二 : 指名道姓的使用父类中的方法

    • 指名道姓的调用, ''名''指的是父类名, 当类来调用方法的时候, 就是在调用普通的函数, 有几个值就要传几个值, 所以要传 "self"
    class Animal:
        def run(self):
            print("奔跑(Animal)")
    
        def eat(self):
            print("吃东西(Animal)")
    
    class Duck(Animal):
        bread = "可爱鸭(Duck)"
    
        def eat(self):
            print("吃东西(Duck)")
    
        def speak(self):
            Animal.eat(self)   # 指名道姓的调用父类中的"eat()"方法, 必须需要添加"self"
            print("嘎嘎嘎(Duck)")
    
    duck1 = Duck()
    duck1.speak()
    '''输出
    吃东西(Animal)
    嘎嘎嘎(Duck)
    '''
    

    3.方式三 : 通过 super() 调用

    • 严格依赖继承属性来查找关系

    • super() 的返回值是一个特殊的对象, 该对象专门用来调用父类中的属性

    • super().__init__() 不用再传入 "self", 因为自动传入

    • python2中需要为 super 传参 super(自己的类名,self)

    • python3中优化可以不用传参 super()

    class Animal:
        def run(self):
            print("奔跑(Animal)")
    
        def eat(self):
            print("吃东西(Animal)")
    
    class Duck(Animal):
        bread = "可爱鸭(Duck)"
    
        def eat(self):
            print("吃东西(Duck)")
    
        def speak(self):
            super(Duck, self).eat()  # python2需要传参 (使用super就不用再传入"self")
            super().eat()            # python3中可以不传 (使用super就不用再传入"self")
            print("嘎嘎嘎(Duck)")
    
    duck1 = Duck()
    
    duck1.speak()
    '''输出
    吃东西(Animal)
    吃东西(Animal)
    嘎嘎嘎(Duck)
    '''
    
    • 示例2
    class People(object):
        school = "蟹堡王餐厅"
    
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class Staff(People):
        def __init__(self,name,age,sex,id):
           # People.__init__(self,name,age,sex)         # 指名道姓的写法
           # super(Staff, self).__init__(name,age,sex)  # python2中super调用的写法
            super().__init__(name,age,sex)              # Python3中super调用的写法
            self.id = id
    
        def sell(self):
            print(f"{self.name}正在卖蟹堡")
    
    S1 = Staff("派大星",22,"man",1)
    
    print(S1.__dict__)  # {'name': '派大星', 'age': 22, 'sex': 'man', 'id': 1}
    

    三.关于 super 调用父类方法的查找顺序

    class F1:
        def s1(self):
            print('F1:s1')
        def s2(self):
            print('F1:s2')
    
    class F2(F1):
        # def s1(self):
        #     print('F2:s1')
        def s2(self):
            print('F2:s2')
    
    class F4():
        def s1(self):
            print('F4:s1')
        def s2(self):
            print('F4:s2')
    
    class F3(F2,F4):
        def s1(self):
            super().s1()  # 调用父类的s1方法,到底使用了哪个父类的s1
        def s2(self):
            print('F3:s2')
    
    
    f1 = F3()
    f1.s1()  # F1:s1
    # 这个示例, 子类最终没有继承同一个父类, 所以是非菱形结构, 每一条路都会找到底
    # 查找顺序 : F3 ===> F2 ===> F1
    

    super 总结

    • super( ) 代指父类对象, 严格按照 mro 列表查找
    • super( ).[属性] : 从父类开始找, 并且是按照 mro 列表查找
    • self.[属性] : 先从自己找, 自己没有就按照 mro 列表找

    ps : 上面这个示例不懂不要紧, 可查看菱形继承问题之后再来思考

    关于多继承的调用涉及到菱形继承问题, 有不同的情况讨论菱形继承问题

  • 相关阅读:
    Python语法入门01
    计算机基础入门
    小白初入Python人工智能
    python编译器的安装和pycharm的安装
    一个简单的例子,让你理解依赖注入
    分分钟教会大家第一个Spring入门案例
    白牌交换机:理想,现状与未来
    2017下一代数据中心网络研究报告
    pica8公司和picOS
    OCP(open compute project)
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14183260.html
Copyright © 2020-2023  润新知