zoukankan      html  css  js  c++  java
  • Python课程回顾(day22)

    类和对象之继承 

    1.什么是继承?

      继承在我们人类现实世界中可以形容为一种遗传,就像孩子与爸爸之间的关系,爸爸可以将所有事物传给孩子的意思..

      而在我们的python中之前也提到过一种继承,是在logging模块里说过的,它跟我们的现实世界恰好相反,是父类继承子类的一种继承

      今天我们所说的这种继承是类和对象中的继承,在程序中继承是一种新建子类的方式,新创建的类被称之为子类/派生类,被继承的类称之为父类/基类/超类,而新创建的子类则可以重用到父类的属性

    2.为何要用继承?

      假设我们的父类有多个子类,而多个子类都要用到相同一段功能,这时候就可以将这段功能放置父类内,不仅子类也可以使用代码,还减少了代码冗余的现象

    3.如何使用继承?

    如下:在继承类的括号内加上被继承类的类名即完成继承,而在python中又分为单继承与多继承的特点

    class Parent1:
        pass
    
    class Parent2
        pass
    
    class Sub1(Parent1):          # 继承Parent1
        pass
    
    class Sub2(Parent1, Parent2): # 继承Parent1与Parent2
        pass

    print(Sub1.__bases__)
    print(Sub2.__bases__) # 使用__bases__查看当前的被继承类(父类)

    python2与python3继承关系的区别

      python2与python3在继承上最大的区别就在于是否继承了object,object也是一个类,是python内部封装好的一些个功能,而在python2中有时是用不到继承object的,但在python3中,默认会直接继承object.总的来说,继承的类型分为两大类:

      新式类:但凡继承了object类的子类以及子子类...,都称之为新式类.

      经典类:但凡没有继承object类的子类以及子子类...,都称之为经典类

    继承的应用1:

    class Oldboy:
        school = 'oldboy'
        pass
    
    class Students(Oldboy):
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def choose_class(self):
            print('%s is choosing class' % self.name)
    
    class Teacher(Oldboy):
        def __init__(self, name, age, gender, level, salary):
            self.name = name
            self.age = age
            self.gender = gender
            self.level = level
            self.salary = salary
        def score(self, stu, num):
            stu.num = num
            print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))
    
    stu = Students('孔令飞', 23, 'male')
    teac = Teacher('egon', 26, 'male', 10, 10000)
    print(stu.school)      # 继承之后可以查找父类的属性
    print(teac.school)     # 继承之后可以查找父类的属性
    

    继承的应用2:

    在子类派生出的新功能中如何重用父类的功能:

    方式一:指名道姓的访问某一类中的函数,与继承无关

    class Oldboy:
        school = 'oldboy'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    class Students(Oldboy):
        def choose_class(self):
            print('%s is choosing class' % self.name)
    
    
    class Teacher(Oldboy):                            
        def __init__(self, name, age, gender, level, salary):
            Oldboy.__init__(self, name, age, gender)  # 直接调用父类的init,减少重复代码,产生对象(直接使用Oldboy内的init函数,与继承无关)
            self.level = level                        # 为其对象添加新的属性
            self.salary = salary
    
        def score(self, stu, num):
            stu.num = num
            print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))
    
    
    stu = Students('孔令飞', 23, 'male')     # 此时调Students等同于调Students内的init函数,但Students内没有就去父类Oldboy找
    # print(stu.__dict__)                   # 证明子类确实重用父类的init函数
    teac = Teacher('egon', 26, 'male', 10, 10000)
    
    stu.choose_class()
    teac.score(stu,100)
    

    属性查找(方式2的前提):

    # 在单继承背景下,无论是经典类还是新式类属性查找顺序都是一样的
    
    # 例:
    
    
    class Foo:
        def f1(self):
            print('Foo.f1')
    
        def f2(self):
            print('Foo.f2')          # 2.打印一
            self.f1()                # 3.打印成功之后又调用自身的f1,若自身内有则打印
    
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')          # 4.打印二
    
    
    obj = Bar()
    obj.f2()                         # 1.首先当前对象内没有f2,然后去类找,类也没有,则去父类
    
    # 在多继承背景下,如果一个子类继承了多个分支,
    # 但是多个分支没有汇聚到一个非object类
    # (汇聚到一点则称之为菱形继承----->(从最低点向上分支又进行汇聚))
    # 无论新式类还是经典类属性查找顺序都是一样的
    # 它会按照从左到右的分支一个一个查找下去
    
    class E:
        xxx = 'E'
    
    
    class F:
        xxx = 'F'
    
    
    class D:
        xxx = 'D'
    
    
    class C(F):
        xxx = 'C'
    
    
    class B(E):
        xxx = 'B'
    
    
    class A(B, C, D):  # 从左到右一个分支一个分支的去找,若分支内也存在继承关系,则会查找完毕后再进入下一个分支查找
        xxx = 'A'
    
    
    obj = A()
    obj.xxx = 1
    print(obj.xxx)
    # 查找顺序为:obj内-->A-->B-->E-->C-->F-->D-->object
    
    # 在多继承背景下,如果一个子类继承了多个分支,
    # 而且多个分支汇聚到了一个非object类
    
    # 新式类:广度优先查找 # 经典类:深处优先查找 class G: pass class E(G): xxx = 'E' class F(G): xxx = 'F' class D(G): xxx = 'D' class C(F): xxx = 'C' class B(E): xxx = 'B' class A(B, C, D): xxx = 'A' obj = A() obj.xxx = 1 print(obj.xxx) # 深度优先查找顺序为:当前对象内-->类-->A-->B-->E-->G-->C-->F-->D # 广度优先查找顺序为:当前对象内-->类-->A-->B-->E-->C-->F-->D-->G-->object

    print(A.mro()) # 根据c3线性化算法算出来的一种属性查找方法,结果是一个列表,会按照列表内的顺序依次进行查找,只要在类定义完成时c3算法会自动算出属性的查找方法
               c3算法无论是否为菱形继承都会算出属性查找方法

    继承的应用2:

    方式二:super方法

    在python3中,super是可以不用传入参数的,调用该函数会得到一个特殊的对象,该对象是专门用来访问父类中的属性的

    super会严格按照当前类的mro列表依次进行属性查找

    class Oldboy:
        school = 'oldboy'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    class Students(Oldboy):
        def choose_class(self):
            print('%s is choosing class' % self.name)
    
    
    class Teacher(Oldboy):                            
        def __init__(self, name, age, gender, level, salary):
            super(Teacher,self).__init__(name,age,gender)     # super方法得到的对象就是专门查找父类属性的,所有直接调用父类的__init__函数来为teac添加属性
            self.level = level                       
            self.salary = salary
    
        def score(self, stu, num):
            stu.num = num
            print('%s老师给%s同学打了%s分' % (self.name, stu.name, num))
    
    
    stu = Students('孔令飞', 23, 'male')   
    # print(stu.__dict__)                   
    teac = Teacher('egon', 26, 'male', 10, 10000)
    
    stu.choose_class()
    teac.score(stu,100)
    
  • 相关阅读:
    ubuntu+VS code+launch.json+task.json
    C++——运行时类型识别RTTI
    C++——模板
    C++——class类和struct结构体的唯一区别
    C++——右值引用
    C++——智能指针
    身份证号码格式检测
    PHP获取图片主题颜色
    PHP 压缩图片质量
    redis3.2装完后 其它机子访问爆protocol error, got 'n' as reply type byte
  • 原文地址:https://www.cnblogs.com/lefy11-/p/9838769.html
Copyright © 2011-2022 走看看