• Python--面向对象之继承


    一 : 初识继承

      继承是为了在在一个类中方便的使用另一个类中的内容.

    class Animal:
        breath = '呼吸'
    
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def eat(self):
            print(self)
            print('动物需要进食....')
    
    
    class Person(Animal):  
        pass

      这段代码中,类Person继承了类Animal,那么我们把类Person称作子类/派生类,把类Animal称作父类/基类/超类. 在python3.x中,所有类默认继承了objec类,如果在定义类的时候不写括号或者括号内没有内容,默认继承objec类.

      子类可以直接使用父类中的内容,比如这个Person类,其中什么都没有,但是在它实例化的时候,会调用父类中的__init__()函数,必须要传入name/sex/age三个参数

    p1 = Person('alex', 'laddyboy', 1000)
    print(p1.__dict__) # {'name': 'alex', 'sex': 'laddyboy', 'age': 1000}
    p1.eat() #<__main__.Person object at 0x0000022FAC4A5390> 动物需要进食....
    print(p1.breath) # 呼吸
    print(p1) # <__main__.Person object at 0x00000195C7FEB390>

      可以看到,当我们调用父类的eat方法,打印self的结果是子类的对象,和打印p1的地址一致,可以通过子类的对象获得父类中的内容.这是因为子类中存在一个指向父类的指针,当调用子类的内容的时候,如果不存在,就会通过这个指针向父类中寻找.原理与类和对象空间的关系相似.

      可以直接在子类中调用父类中的内容,可以通过两种方法办到,其一是直接用父类名 . 变量名/方法名  的方式,其二是 用 super() . 变量名/方法名 的方式,推荐用第二种方法,因为python是支持多继承的,这种方法泛用性更高.

    class Animal:
        def __init__(self, name, sex, age):
            self.name = name
            self.sex = sex
            self.age = age
    
        def eat(self, a1):
            print('%s吃%s' % (self.name, a1))
    
        def drink(self):
            print('%s喝东西' % (self.name))
    
    
    class Cat(Animal):
    
        def miaow(self):
            print('喵喵叫')
        def drink(self):  # 只执行自己类中的方法
            print('类Cat中的drink')
    
    
    class Brid(Animal):
    
        def __init__(self, name, sex, age, wing):
            # Animal.__init__(self, name, sex, age) 这是第一种方法
            super().__init__(name, sex, age)  #  第二种方法(推荐) super(Brid,self).__init__(name,sex,age)这是完整版的调用方式,括号里的父类名和self是可以省略的
            self.wing = wing
    
        def bark(self):
            print('嗷嗷叫')
    
        def eat(self, argv):
            super().eat(argv)
            print('鸟吃虫子...')
    
    
    c1 = Cat('LiFuGui', '雄性', 2) #实例化一只猫
    c1.drink() # 调用dring()方法, 此时子类和父类中都有名为dring的方法  打印结果 : 类Cat中的drink
    c1.eat('耗子') # 子类中没有eat方法,于是调用父类中的eat方法  打印结果:LiFuGui吃耗子

    二 : 多继承

      一条线的继承很好理解,父类中没有的内容会向父类的父类中寻找,代码如下

    class A:
        def func(self):
            print('IN A')
    
    class B(A):
        pass
        # def func(self):
        #     print('IN B')
    
    class C(B):
        pass
    
    c1= C()
    c1.func() # IN A

      麻烦的是一个类同时有多个父类:

    class A:
        def func(self):
            print('IN A')
    
    class B(A):
        pass
        # def func(self):
        #     print('IN B')
    
    class C(A):
        pass
        # def func(self):
        #     print('IN C')
    
    class D(B):
        pass
        # def func(self):
        #     print('IN D')
    
    class E(C):
        pass
        # def func(self):
        #     print('IN E')
    
    class F(D,E):
        pass
        # def func(self):
        #     print('IN F')
    
    f1 = F()
    f1.func()

      通过mro函数可以获得一个类的继承路线,当它向父类寻找一个内容的时候,会遵循这个顺序

    print(F.mro()) #[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

      这个顺序是通过C3算法得到的,我们不通过mro()函数,可以通过merge list和拓扑排序两种方式获得这个顺序.因为这两种方式太复杂,再次不再描述.

      

  • 相关阅读:
    C# 使用Dev控件为gridView添加复选框,实现多选和单选
    C# 关于LINQ基础随笔
    Camstar客制化开发做查询操作(Designer中存放SQL语句)
    ASP.NET 实现自动登录(自定义自动登录时间期限)
    ASP.NET 页面生命周期-动态控件编程(动态添加控件并使用动态控件值)
    Camstar客制化开发查询数据库数据并显示在JQDataGrid表中(SQL语句编写在UserQuery中)同时获取JQDataGrid中值回传到Designer中
    Camstar客制化开发查询数据库数据并显示在JQDataGrid表中(SQL语句编写在代码中)
    WPF开发中常用的几种布局元素
    Cocos2dx 内存管理机制(1)
    cocos2dx 坐标系统详解
  • 原文地址:https://www.cnblogs.com/DoingBe/p/9433740.html
Copyright © 2020-2023  润新知