• Python 类抽象与继承 派生覆盖 组合 属性查找顺序 新式类菱形继承


    一 继承与抽象(类与类之间的关系)

    1.什么是继承:在程序中继承是描述类与类之间的关系。例如:A类继承了B类,A类就能直接使用B类已经存在的方法和属性(A类称之为子类,B类称之为父类也叫基类)

    2.为什么要使用继承:继承的一方可以直接使用被继承一方已经存在的方法和属性。其目的是为了提高代码的复用性。

    3.继承语法

    class 父类名称:
        类的内容 
    
    class 子类名称(父类名称):
        类的内容 
        
    #在python中 一个子类可以同时继承多个父类 
    View Code

    抽象

    1.什么是抽象:将多个子类中相同的属性和方法,进行抽取形成一个新的类。再有别的子类们进行继承。

    2.例:

    class Teacher:
        school = "oldboy"
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def say_hi(self):
            print("hello i am %s" % self.name)
            
        def teach(self):
            print("正在教书......")
    
    class Student(Teacher):
        pass
    # 问题:学生类继承了老师类,所以学生类都具备了老师类的name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不应该具备。
    # 解决:抽象
    
    class OldBoyPerson:
        school = "oldboy"
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def say_hi(self):
            print("hello i am %s" % self.name)
    
    class Teacher(OldBoyPerson):
        def teach(self):
            print("正在教书......")
    
    
    class Student(OldBoyPerson):
        pass
    # 学生类和老师类继承了OldBoyPerson类,都具备name,age属性和say_hi,teacher方法。但是teacher方法应该是老师独有的,学生不具备。
    View Code

    3.继承的正确使用:先抽象再继承

    二 对象属性和方法正确的查找顺序

    class A:
        text = "haha"
    
    class B(A):
        text = "heihei"
        pass
    
    b = B()
    b.text = "xixi"
    
    print(b.text) # xixi"
    
    对象自己的 - > 所在类中 -> 找父类 - >父类的父类 ->Object
    View Code

    三 继承中的覆盖与派生

    1.什么是覆盖(重写):指的是子类中出现了与父类相同的属性或方法。(根据查找顺序就会优先查找自己的即覆盖了父类的属性和方法。

    2什么是派生:子类中出现了和父类不一样的属性或方法。

    class Person:
        name = 'person'
        def say_hi(self):
            print("hello")
    
    class Student(Person):
        name = 'student'  # 覆盖
        age= 18 # 派生
        def say_hi(self): # 覆盖
            print("hello world!")
    
    
    
    
    stu = Student()
    print(stu.name) # student
    print(stu.age) # 18
    stu.say_hi() # hello world!
    View Code

    四 继承中子类中访问父类的内容的三种方式

    方式1:
    super(当前类名称,self).你要调的父类的属性或方法
    方式2:
    super().你要调的父类的属性或方法,推荐使用
    方式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() # abc anything
    View Code
    class Person:
        text = "321"
        def __init__(self,name,age,gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def sleep(self):
            print("人类 午睡 躺着睡!")
    
        def say_hi(self):
            print("my name :%s my age :%s my gender: %s " % (self.name,self.age,self.gender),end="")
    
        
    class Student(Person):
        text = "123"
        def __init__(self,name,age,gender,number):
            #======================================================================重点在这里
            # 由于父类已经存在一个方法可以完成这个三参数的初始化
            # 所以可以直接调用父类的初始化完成这部分的初始化工作
            # 方法1
            # Person.__init__(self,name,age,gender) # 指名道姓的调用
    
            # 方法2  在py2中不支持
            super().__init__(name,age,gender)
    
            # 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)
            # print("my name :%s my age :%s my gender: %s my number: %s" % (self.name, self.age, self.gender,self.number))
    
    
    s = Student("jack",20,"man","007")
    s.say_hi()
    # s.show_text()

    五 组合

    1.什么是组合:将一个对象作为另一个对象的属性称之为组合(指的是对象与对象之间的关系

    2.组合描述的是 什么拥有什么的关系   学生 有 书  学生有手机

    class PC:
        def open_app(self,app_name):
            print("open %s" % app_name)
    
    class OldBoyStudent:
        def __init__(self,PC,notebook):
            self.PC = PC
            self.notebook = notebook
        pass
    
    pc = PC()
    notebook = PC()
    
    
    stu = OldBoyStudent(pc,notebook)
    View Code
    stu.notebook.open_app("pycharm")
    组合的目的:

    也是为了重用现有代码

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

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

    另外组合相比继承,耦合度更低了

    六 新式类和经典类

    1.新式类:python3中任何类都直接或间接继承了object,python3中全都是新式类

    2.经典类:既不是object的子类,仅在python2中出现,,

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

    class A:
        # a = 1
        pass
    
    class B(A):
        # a = 2
        pass
    
    class C(A):
        # a = 3
        pass
    
    class D(A):
        # a = 4
        pass
    
    class E(B,C,D):
        # a = 5
        pass
    
    e1 = E()
    # print(e1.a)
    # 新式类的顺序
    # E  B C D A object 
    # 经典类的顺序
    # E B A C D
    # print(E.mro())
    
    注意:经典类没有mro列表

    七 实现一个可以限制元素的类型的列表

    """
    需求 实现一个能够限制元素类型的列表类
    
    """
    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
    class A:
        # a = 1
        pass
    
    class B(A):
        # a = 2
        pass
    
    class C(A):
        # a = 3
        pass
    
    class D(A):
        # a = 4
        pass
    
    class E(B,C,D):
        # a = 5
        pass
    
    e1 = E()
    # print(e1.a)
    # 新式类的顺序
    # E  B C D A object
    # 经典类的顺序
    # E B A C D
    print(E.mro()) # <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>]
    
    # 注意:经典类没有mro列表
    View Code
  • 相关阅读:
    Manage Files on HDFS via Cli/Ambari Files View——如何在ambari上查看HDFS文件
    Windows Authentication
    request.getParameterMap 无法获取到参数的原因
    sql server 分割字符串存储过程
    URI.js – 全能的URL操作库
    低延迟视频流播放方案探索
    mysql 替换函数replace()实现mysql替换指定字段中的字符串
    如何在npm上发布自己的包
    sharp 安装过慢
    Error: EACCES: permission denied, mkdir
  • 原文地址:https://www.cnblogs.com/tfzz/p/11247043.html
Copyright © 2020-2023  润新知