zoukankan      html  css  js  c++  java
  • d21天 继承

    继承是一种关系,通过继承关系,一个对象可以直接使用另一个对象已定义的方法和属性,描述的是类与类之间的关系

    被继承的称之为父类或基类或超类,继承父类的类称之为子类或派生类;

    在OOP中 继承描述是类和类之间的关系 例如b类继承a类 b类可以直接使用a类中的属性和方法

    用继承的好处:

    继承的一方可以直接使用被继承一方已经有的东西 
    
    其目的是为了重用已经有的代码,提高重用性 
    如何使用继承
    
    语法:
    在类名后面的括号中指定要继承的父类名称
    python
    class 类名称(父类的名称):
        类的内容 
        
    #在python中 一个子类可以同时继承多个父类 

    例子:

    class Base:
        desc = '这是一个基类'
    
        def show_info(self):
            print(Base.desc)
        def make_money(self):
            print('一天一个亿')
    
    
    # 指定父类位Base
    class Subclass(Base):
        # def make_money(self):
            pass
            # print('一天一百')
    
    obj = Subclass()
    obj.make_money()
    print(obj.desc)
    View Code

    抽象与继承

    继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承

    继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

    抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类

    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("jack","male",20)
    t1.say_hi()
    
    
    class  Student(Person):
        pass
    
    stu1 = Student("rose","female",18)
    stu1.say_hi()
    View Code

    抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度),每个类之干自己的事情,多个类相同的事情交给父类来干

    属性的查找顺序

    一个类必然继承另一个类,被继承的类也有可能继承了其他类,相当于C继承B,B又继承A

    此时查找属性的顺序是:

    对象本身的名称空间 - > 类的名称空间 -> 父类的名称空间 -> 父类的父类名称空间 ->...object类

    会沿着继承关系一直往后查找,直到找到为止,由于object是所有类的根类,所以如果找不着最后都会查找object类!

    class A:
        text = "haha"
    
    class B(A):
        text = "heihei"
        pass
    
    b = B()
    b.text = "xixi"
    print(b.text)
    class ParentClass1:
        pass
    
    class ParentClass2:
        pass
    
    class SubClass1(ParentClass1):
        pass
    
    class SubClass2(ParentClass1,ParentClass2):
        pass
    # __base__只查看从左到右继承的第一个子类,
    # __bases__则是查看所有继承的父类
    print(SubClass1.__bases__)
    
    print(SubClass2.__bases__)
    
    print(SubClass2.__base__)
    View Code

    派生与覆盖

    派生 当一个类继承自另一个类 并且这个子类拥有与父类不同的内容 就称之为派生

    class A:
        def info(self):
            print('hello world')
    class B:
        pass

    覆盖 (重写) 子类中出现了与父类名称相同的属性 或方法 就会覆盖掉父类的属性或方法

    class A:
        text='124'
        def info(self):
            print('hello')
    
    class B(A):
        text='529'
        def info(self):
            print('hello,asedrk')
        pass
    
    b=B()
    b.info()
    print(b.text)
    View Code

    练习:

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

    需求 实现一个能够限制元素类型的列表类
    
    """
    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")
    View Code

    子类访问父类的内容

    语法

    方式1:
    super(当前类名称,self).你要调的父类的属性或方法
    方式2:
    super().你要调的父类的属性或方法
    方式3:
    类名称.你要调的父类的属性或方法(self)  
    #方式3与继承无关 

    例子

    class Person:
        text='147'
        def __init__(self,name,age,):
            self.name=name
            self.age=age
    
        def sleep(self):
            print('吃饭,睡觉,打豆豆')
        def say_no(self):
            print('name:%s,age:%s'%(self.name,self.age),end='')
    
    class Student(Person):
        text='852'
    
    # 由于父类已经存在一个方法可以完成这个三参数的初始化
    # 所以可以直接调用父类的初始化完成这部分的初始化工作
    
    def __init__(self,name ,age,number):
            # [1]指名道姓的调用
            Person.__init__(self,name,age)
            # [2]super()
            super().__init__(name,age)
    
            # py2的写法
            # super(Student, self).__init__(name,age,gender)
    
            self.number=number
            
            # 访问父类的属性
        def show_text(self):
            print(self.text)
            print(super().text)
    
        def say_hi(self):
            super().say_hi()
            print("my number: %s" % self.number)
    
    s = Student("jack",20,"man",)
    s.say_no()
    View Code

    调用 父类的初始化方法

    当你继承一个现有的类,并且你覆盖了父类的init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需的参数 
    View Code

    例子:

    class Person:
        def __init__(self,name,gender,age,*args):
            self.name = name
            self.gender = gender
            self.age = age
            self.aa()
    
        def aa(self):
            print("aa run")
    
    
        def say_hi(self):
            print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))
    
    
    class Student(Person):
    
        def __init__(self,name,gender,age,number):
            super().__init__(name,gender,age)
            self.number= number
    
        def say_hi(self):
            super().say_hi()
            print("numnber:%s" % self.number)
    
    stu = Student("rose","mael",20,"old01")
    stu.say_hi()
    View Code

    继承的原理,mro列表

    即使没有直接继承关系,super仍然会按照mro继续往后查找

    当你使用super()函数时,
    # Python会在MRO列表上继续搜索下一个类。
    # 只要每个重定义的方法统一使用super()并只调用它一次
    # ,那么控制流最终会遍历完整个MRO列表,
    # 每个方法也只会被调用一次
    View Code

    使用super调用的所有属性,都是从MRO列表当前的位置往后找

    class A():
        # q=3
        pass
    
    class B(A):
        # q=5
        pass
    
    class C(A):
        q=9
        pass
    
    class D(B,C):
        # q=15
        pass
    
    Q=D()
    print(Q.q)
    print(D.mro()) 
    View Code

    组合

    指的是 一个类把另一个类的对象作为自己的属性 就称之为组合
    当你定义一个类 并且这个类拥有某种类型的属性时 就称之为组合
    对象与对象的关系
    都是用用来重用代码的方式:
    组合描述的是 什么拥有什么的关系   学生 有 书  学生有手机
    继承描述的是 什么是什么的关系      麦兜是猪    猪猪侠也是猪

    例子

    class Phone:
        def __init__(self,price,kind,color):
            self.price = price
            self.kind = kind
            self.color = color
    
        def call(self):
            print("正在呼叫XXXX;")
    
        def send_message(self):
            print("正在发送短信....")
    
    
    class Student:
        def __init__(self,name,gender,phone):
            self.name = name
            self.gender = gender
            self.phone = phone
    
        def show_info(self):
            print("name:%s gender:%s" % (self.name,self.gender))
    
    phone = Phone(1000,"apple","red")
    
    stu1 = Student("rose","male",phone)
    stu1.phone.call()
    View Code

    经典类与新式类

    1.只有在python2中才分新式类和经典类,python3中统一都是新式类
    2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
    3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
    3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式

     

    经典类:
      深度优先
    新式类:
    先深度 直到有一个公共父类时,查找其他路线(基于C3算法)

    菱形继承

    一个类有多个父类,多个父类又有一个公共的父类

     

     

    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)
    View Code
  • 相关阅读:
    tbody的有趣问题
    如何去掉a标签的虚框
    在ubuntu下安装ruby on rails环境
    odoo 新建模块命令
    安装sentry的几个命令,日志监控系统
    腾讯云docker加速
    odoo技术笔记
    零基础实现摄像头的全平台直播 (一)内网直播的实现
    EasyNVR、EasyDSS二次开发RTMP、HLS流在web页面进行无插件播放(demo)
    EasyDSS流媒体服务器和EasyDSS云平台异同
  • 原文地址:https://www.cnblogs.com/komorebi/p/11247138.html
Copyright © 2011-2022 走看看