• 继承


    一、什么是继承?

      继承是一种关系,描述两个对象之间,什么是什么的关系:

    新建的类可以继承一个或多个父类,父类有被称为基类或超类,新建的类型称为派生类或子类,在python中有单继承和多继承

    class Base:
        ser="这是一个基类"
        def show_info(self):
            print(self.ser)
    
        def make_money(self):
            print("哎!苦逼的一天")
            # 指定父类位Base
    
    class Subclass(Base):
        pass
    obj=Subclass() # 即使类中什么都没有也可以使用父集中已经有的内容
    obj.make_money()
    print(obj.ser)

      在程序中,继承描述的是类和类之间的关系,例如:a继承了b,a就能直接使用b已经存在的方法和属性。

    查看继承:

    print(Subclass.__bases__)

    二、抽象与继承:抽象就是不清晰、不具体、很迷糊
      抽象即抽取类似或者说比较像的部分:将人,猪,狗这三个类比较像的部分抽取成父类。 动物
     正确的使用继承:
      1、先抽象再继承
      2、继承一个已经现存的类,扩展或是修改原始的功能
    继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
    # 抽取老师和学生中相同的部分形成person类
    class Person:
        def __init__(self,name,age,gender):
            self.name=name
            self.age=age
            self.gender=gender
        def say_hi(self):
            print("name:%s,gender:%s,age:%s"%(self.name,self.gender,self.age))
    class Teacher(Person): #  调用 使代码的重复性降低
        # def teaching(self):
            print("老师上课就犯困...!")
    t1=Teacher("Json","female",20)
    t1.say_hi()
    
    class Student(Person):# 调用同样属性的特征
            pass
    stu1=Student("Reso","male",18)
    stu1.say_hi()
    
    
    “子类调用了父类的同样年龄、姓名、性别的属性,使得代码没有那么重复”

    三、派生

      当一个子类中出现了与父类中不同的内容时,这个子类就称之为派生类;

    通常子类都会写一些新的代码,不可能和父类完全一致,即通常都是派生类,所以派生类指的就是子类

    class Person:
        def say_hi(self):
            print("hello")
    
    class Student(Person):
        def say_hi(self):
            print("hello world!")
    
    stu = Student()
    stu.say_hi()

    四、覆盖:

      也称之为重写:overrides 当子类出现了与父类名称完全一致的属性或方法

      根据查找顺序,优先使用子类中的属性,这种行为也称为覆盖

    五、属性的查找顺序:

      对象自己的-->>所在的类中->>找父类->>父类的父类->>Object(对象)

    class A:
        text="heihei"
    class B(A):
        text="haha"
    class C(B):
        text="dogdog"
        pass
    b=B()
    b.text="are you ok"
    print(b.text)
    
    c=C()
    c.text="aabb"
    print(c.text)
    
    >>
    
    are you ok
    aabb

    六、子类访问父类的内容 

      语法:调用super()

    方式1:
    super(当前类名称,self).你要调的父类的属性或方法
    方式2:
    super().你要调的父类的属性或方法 # 访问方式2 py3的新语法 最常用的方式
    方式3: 类名称.你要调的父类的属性或方法(self) 

    #方式3与继承无关
    class Parent:
        text = "abc"
        def say_something(self):
            print("anything")
    class Sub(Parent):
        def show_info(self):
            # print(super(Sub,self).text)
            # super(Sub,self).say_something()
            # 访问方式2  py3的新语法 最常用的方式
            print(super().text)
            super().say_something()
            #方式3 直接指定类名调用
            # print(Parent.text)
            # Parent.say_something(self)
    sub = Sub()
    sub.show_info()
    
    
    >>>
        why?

    重点:

      当你要继承一个出现有的类,并覆盖了父类的__init__的方法时,必须在初始化方法的第一行调用父类

    的初始化,并传入父类所需的参数( 应用的场景是需要有特定的限制条件时 )

    class Student(Person):

    def __init__(self,name,gender,age,number):
    super().__init__(name,gender,age) # 类的属性中有多余的number 使用前必须先定义
    self.number= number

    需求:需要实现一个可以限制元素类型的容器(字典,列表,元组,集合,字符串

    class MyList(list):
        def __init__(self,element_type):
            super().__init__() # 调用父类的初始化方法 来完成基本的初始化,
            self.element_type = element_type #一开始定义就设置限定条件
    
        def append(self, object):
            """
            :param object: 是要存储的元素
            :return: 没有
            """
            if type(object) == self.element_type:
                #我们需要在这里访问父类的append函数来完成真正的存储操作
                super(MyList,self).append(object)
            else:
                print("sorry sir, you element type not is %s" % self.element_type)
    
    
    # 创建是指定要存储的元素类型
    m = MyList(int)
    # 当你有需求,是需要在创建对象时 干点什么事儿 那就该想到初始化方法
    
    m.append(1)
    print(m[0])
    m.append("121212")

       当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。如果每个重定义的方法统一使用super()并只调用它一次,

    那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次

    (注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

    #A没有继承B,但是A内super会基于C.mro()继续往后找
    class A:
        def test(self):
            super().test()
    class B:
        def test(self):
            print('from B')
    class C(A,B):
        pass
    
    c=C()
    c.test() #打印结果:from B
    
    
    print(C.mro())
    #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

    七、组合:

      指的是:在一个类中以另外一个类的对象做为数据属性称为类的组合

      例如:学生有手机,游戏中角色拥有某些技能(即有什么有什么)

    组合的目的: 也是重用现有的代码

     

    什么时候使用继承:分析两个类的关系,到底是不是:什么是什么的关系

    什么时候使用组合:如果两个类之间 没有太大的关系,完全不属于同类

    八、菱形继承:

    补充:新式类与经典类

    python3中任何类都是直接或间接继承了Object

    新式类,任何显式或隐式地继承自object的类就称之为新式类, python3中全都是默认为新式类 

    经典类,既不是Object的子类 ,仅在python2中出现 

     

    • 当类是经典类时,多继承情况下,会按照深度优先方式查找
    • 当类是新式类时,多继承情况下,会按照广度优先方式查找

    菱形继承
    class A:
        j = 1
        pass
    class B:
        # j = 2
        pass
    class C(A):
        # j = 3
        pass
    class D(A):
        j = 4
        pass
    class E(B,C,D):
        # j = 5
        pass
    d = E()
    print(d.j)

    当出现了菱形继承时,新式类,先深度,当遇到了共同父类时就广度 ,新式类,就是深度优先

     

     

     

    继承面试题:

    class Init(object):
         def __init__(self, v):
             print("init")
             self.val = v
    class Add2(Init):
         def __init__(self, val):
             print("Add2")
             super(Add2, self).__init__(val)
             print(self.val)
             self.val += 2
    class Mult(Init):
         def __init__(self, val):
             print("Mult")
             super(Mult, self).__init__(val)
             self.val *= 5
    class HaHa(Init):
         def __init__(self, val):
             print("哈哈")
             super(HaHa, self).__init__(val)
             self.val /= 5
    class Pro(Add2,Mult,HaHa): #
         pass
    class Incr(Pro):
         def __init__(self, val):
             super(Incr, self).__init__(val)
            self.val+= 1
    # Incr Pro Add2 Mult HaHa Init
    p = Incr(5)
    print(p.val)
    c = Add2(2)
    print(c.val)

     

      

     

     

     

     

     

     

     




      


     

     

  • 相关阅读:
    一些常用的表单验证的代码
    JQuery 在线参考手册
    jQuery ajax
    DIV+CSS专题:十天学会DIV+CSS
    wordpress调用函数大全
    WordPress 主题教程:从零开始制作 WordPress 主题
    全面提升WordPress前台和后台的 打开速度的方案
    详细的图文介绍如何利用XAMPP本地建站的环境配置教程
    2014年,daliu_it 年末文章汇总清单
    再见,2014;您好,2015!
  • 原文地址:https://www.cnblogs.com/Gaimo/p/11247426.html
Copyright © 2020-2023  润新知