zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    cf1100 F. Ivan and Burgers
    cf 1033 D. Divisors
    LeetCode 17. 电话号码的字母组合
    LeetCode 491. 递增的子序列
    LeetCode 459.重复的子字符串
    LeetCode 504. 七进制数
    LeetCode 3.无重复字符的最长子串
    LeetCode 16.06. 最小差
    LeetCode 77. 组合
    LeetCode 611. 有效三角形个数
  • 原文地址:https://www.cnblogs.com/tfzz/p/11247043.html
Copyright © 2011-2022 走看看