• [python基础] 面向对象——封装,继承


    一、面向对象的基础知识

    1、面向对象
    定义:面向对象是人们按照客观世界的系统思维,把构成问题的事物分解成各个对象,建立对象的可以更好的描述某个事物在整个解决问题的步骤中的行为。
    特点:抽象 封装 集成 多态
    优点:易维护,易服用,易扩展。可以设计出低耦合的系统,使系统更加灵活,更加容易维护
    缺点:性能比面向过程低

    2、类(Class)
    类是显示或者思维世界中的实体在计算机中的反映,它将数据以及这些数据上的操作封装在一起。

    3、对象(Object)
    对象是具有类类型的变量,类和对象是面向对象编程技术中的最基本的概念
    类和对象是类似与鱼和草鱼的关系。

    二、类和面向对象

    类和对象的使用

    # 类(Class)
    class Cat:
        # 属性:一般是名词,eg: name, age, gender.....
        name = 'name'
        kind = 'kind'
    
        # 方法: 一般情况是动词, eg: create, delete, eating, run......
        def eat(self):
            print('cat like eating fish.....')
    
    # 对象(Object):对类的实例化(具体化)
    fentiao = Cat()
    
    print(Cat)  # <class '__main__.Cat'>
    print(fentiao) # <__main__.Cat object at 0x00E9FD70>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    三、封装

    1、基本使用方法

    class Cat:
        def __init__(self, name, kind):  # 形参
            """
            1. 构造方法,实例化对象时自动执行的方法
            2. self是什么? self实质上是实例化的对象
            3. 类方法中, python解释器会自动把对象作为参数传给self
            """
            print('正在执行__init__构造方法')
            print('self:', self)
    
            # 属性:一般是名词,eg: name, age, gender.....
            # 封装: self.name将对象和name属性封装/绑定
            self.name = name
            self.kind = kind
    
        # 方法: 一般情况是动词, eg: create, delete, eating, run......
        def eat(self):
            print(f'cat {self.name} like eating fish.....' )
    
    
    # 对象(Object):对类的实例化(具体化)
    fentiao = Cat("粉条", "美短虎斑")
    print(fentiao.name)
    print(fentiao.kind)
    fentiao.eat()
    
    #结果
    正在执行__init__构造方法
    self: <__main__.Cat object at 0x000001B916A623B0>
    粉条
    美短虎斑
    cat 粉条 like eating fish.....
    cat 粉条 like eating fish.....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    2、练习
    要求:
    创建一个类people
    拥有的数学为姓名,性别和年龄
    拥有的方法为购物,学习,玩游戏

    实例化对象,执行对应的方法

    显示如下:
    小明,18岁,男,去赛格广场购物。
    小王,22岁,男,去赛格广场购物
    小红,10岁,女,在西部开源学习

    代码如下:

    class people:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
        def shopping(self):
            print(f'{self.name},{self.age}岁,{self.gender},去西安赛格广场购物')
    
        def learning(self):
            print(f'{self.name},{self.age}岁,{self.gender},在学习')
    
    
    p1 = people('小明', '18', '男')
    p2 = people('小王', '18', '男')
    p3 = people('小红', '10', '女')
    
    p1.shopping()
    p2.shopping()
    p3.learning()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    四、继承

    (1)、基本使用方法

    父类又称基类
    子类又称扩展类
    1、继承的使用方法
    当子类没有时找父类的执行方法

    class Student:
        """父类Student"""
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def learning(self):
            print(f'{self.name}正在学习')
    
    class MathStudent(Student):
        """MathStudent的父类是Student"""
        pass
    
    
    # 实例化
    m1 = MathStudent("粉条博士", 8)
    print(m1.name)
    print(m1.age)
    m1.learning()           # 不报错,子类里没有,但父类有该方法
    # m1.choice_course()    # 报错, 子类里没有,父类也没有的方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、继承的使用方法扩展
    当子类和父类都有对应的执行方法时,会执行子类的执行方法。
    如果需要先执行父类的执行方法,再执行子类的执行方法,则用在子类函数里面添加super函数。

    class Student:
        """父类Student"""
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def learning(self):
            print(f'{self.name}正在学习')
    
        def choice_course(self):
            print('正在选课中'.center(50, '*'))
    
    class MathStudent(Student):
        """MathStudent的父类是Student"""
        def choice_course(self):
            # 需求: 先执行父类的choice_course方法, 在个性化执行自己的方法。
            # Student.choice_course(self)  # 解决方法1: 直接执行父类的方法,但不建议
            # 解决方法2: 通过super找到父类,再执行方法(建议且生产环境代码常用的方式)
            super(MathStudent, self).choice_course()
            info = """
                        课程表
                1. 高等数学
                2. 线性代数
                3. 概率论
            """
            print(info)
    
    # 实例化
    m1 = MathStudent("粉条博士", 8)
    m1.choice_course()
    
    s1 = Student("粉条博士", 8)
    s1.choice_course()
    
    #结果
    **********************正在选课中***********************
    
                        课程表
                1. 高等数学
                2. 线性代数
                3. 概率论
            
    **********************正在选课中***********************
    
    Process finished with exit code 0
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    (2)、链表相加

    参考链接 https://www.cnblogs.com/klyjb/p/11237361.html

    数组: 需要连续的内存空间
    链表: 不需要连续的内存空间
    
    • 1
    • 2

    不同的数据结果对应的时间复杂度不同,数据和链表的复杂度如下:

                    数组              链表
    增加元素        O(n)                O(1)
    删除元素        O(n)                O(1)
    修改元素        O(1)                O(n)
    查看元素        O(1)                O(n)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在这里插入图片描述

    # 封装节点类
    
    class ListNode:
        # 首先封装传值
        def __init__(self, val=0, next=None):            #指针类型为空
            self.val = val
            self.next = next
    
         # 定义链表寻值方式
        def travel(self, head):
            """遍历链表里面的每一个元素"""
            while head:
                print(head.val, end=',')
                head = head.next
    
    #创建第一个链表
    def create_l1():
        # l1 = 2,4,3
        # l2 = 5, 6, 4
        l1 = ListNode()
        node1 = ListNode(val=2)
        node2 = ListNode(val=4)
        node3 = ListNode(val=3)
        l1.next = node1
        node1.next = node2
        node2.next = node3
        return  l1.next
    
    #创建第二个链表
    def create_l2():
        # l1 = 2,4,3
        # l2 = 5, 6, 4
        l2 = ListNode()
        node1 = ListNode(val=5)
        node2 = ListNode(val=6)
        node3 = ListNode(val=4)
        l2.next = node1
        node1.next = node2
        node2.next = node3
        return  l2.next
    
    def addTwoNumbers(l1: ListNode, l2: ListNode) -> ListNode:
        res = 0
        l3 = ListNode()
        cur = l3
        while(l1 or l2):
            if(l1):
                res += l1.val  # res=2
                l1 = l1.next
            if(l2):
                res += l2.val # res=2+5=7
                l2 = l2.next
            # res=10, val=0, res=>val val=res%10
            # res=14, val=4, 14%10=4
            l3.next = ListNode(res%10)
            l3 = l3.next
            # res=10, 进位为1, 10//10=1
            # res=14, 进位为1, 14//10=1
            res  //= 10
        if res == 1:
            l3.next = ListNode(1)
        return cur.next
    
    #直接执行这个模块时会运行以下的代码
    if __name__ == '__main__':
        l1 = create_l1()
        l2 = create_l2()
        l3 = addTwoNumbers(l1, l2)
        l3.travel(l3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    (3)、多继承

    多继承
    python3:新式类(广度优先),多继承时搜索同级优先
    python2:经典类(深度优先),多继承时搜索父级优先

    (4)、私有属性与私有方法

     私有属性,以双下划线开头。
     工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
     
     私有方法是以双下划线开头的方法,
     工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    class Student:
        """父类Student"""
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            # 私有属性,以双下划线开头。
            # 工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
            self.__score = score
    
        def learning(self):
            print(f'{self.name}正在学习')
    
        def get_score(self):
            self.__modify_score()                 #内部使用,调用私有方法
            return  self.__score                  #内部调用,可以使用私有属性
    
        # 私有方法是以双下划线开头的方法,
        #工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
        def __modify_score(self):                 #定义私有方法
            self.__score += 20
    
    s1 = Student('ck',18,425)
    score = s1.get_score()
    print(score)
    #结果
    445
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意:子类无法调用父类的私有方法和属性

    class Student:
        """父类Student"""
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            # 私有属性,以双下划线开头。
            # 工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
            self.__score = score
    
        def learning(self):
            print(f'{self.name}正在学习')
    
        def get_score(self):
            self.__modify_score()                 #内部使用,调用私有方法
            return  self.__score                  #内部调用,可以使用私有属性
    
        # 私有方法是以双下划线开头的方法,
        #工作机制: 类的外部(包括子类)不能访问和操作,类的内部可以访问和操作。
        def __modify_score(self):                 #定义私有方法
            self.__score += 20
    
    
    class MathStudent(Student):
        """MathStudent的父类是Student"""
        def get_score(self):
            self.__modify_score()
            return  self.__score
    
    # 报错原因: 子类无法继承父类的私有属性和私有方法。
    s1 = MathStudent('张三', 18, 100)
    score = s1.get_score()
    print(score)
    # 结果
    AttributeError: 'MathStudent' object has no attribute '_MathStudent__modify_score'. Did you mean: '_Student__modify_score'?
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    补充练习题
    给定一个整型数组nums,和一个整数的目标值target,请找出数组中两个数相加为target的两个整数,并返还器数组下标。
    例:
    输入nums[2,7,11,15],target=9
    输出[0,1]
    解释:因为nums[0]+nums[1]=9

    class solution:
        def twosum(self,nums:list[int],target:int) -> list[int]:
            #用哈希表(python里面是字典)时间复杂度更快
            hashes = {}
            n = len(nums)
            for i in range(n):
           		hashes[nums[i]] = i     #对字典每个值进行赋值,赋的值为索引
                if target - nums[i] in hashes:
                    return hashes[target-nums[i]],i
                
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    使用OpenCV的函数hconcat()、vconcat()实现图像或矩阵的连接
    Intel Cyclone 10 GX 收发器的初步认识
    提取设备中所有APP的唯一标识符,判断每个APP的测试优先级,而后再进行测试安排
    ChatGpt接口流式输出解决方案
    嵌入式实时操作系统的设计与开发 (邮箱)
    C/C++语言100题练习计划 78——括号序列(前缀和实现)
    我常用的5个效率小工具,强烈推荐
    Java8Stream 流的使用
    Final IK⭐四、手指位置适配HandPoser
    说说你对vue的mixin的理解,有什么应用场景
  • 原文地址:https://blog.csdn.net/weixin_48819467/article/details/125553667