• Python自学笔记——高级篇(面向对象)


    本笔记参考视频为:https://www.bilibili.com/video/BV1ex411x7Em?p=101,有兴趣的可以直接移步B站

    1 面向对象(OPP)基本概念

    面向对象编程——Object Oriented Orogramming简写OOP

    • 之前学习的编程方式是面向过程
    • 面向过程和面向对象,是两种不同的编程方式

    1.1 过程和函数

    • 过程是早期的一个编程概念
    • 过程类似于函数,只能执行,但是没有返回值
    • 函数不仅能执行,还可以返回结果

    1.2 面向过程和面向对象基本概念

    • 面向过程
      • 把完成某一个需求的所有步骤从头到尾逐步实现
      • 根据开发需求,将某些功能独立的代码封装成一个又一个函数
      • 最后完成的代码,就是顺序地调用不同的函数
      • 特点:
        • 注重步骤与过程,不注重职责分工
        • 如果需求复杂,代码会变得很复杂
        • 开发复杂项目,没有固定的套路,开发难度很大!
    • 面向对象
      • 相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
      • 在完成某一个需求前,首先确定职责——要做的事情(方法)
      • 根据职责确定不同的对象,在对象内部封装不同的方法(多个)
      • 最后完成的代码,就是顺序地让不同的对象调用不同的方法
      • 特点:
        • 注重对象和职责,不同的对象承担不同的职责
        • 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
        • 需要在面向过程的基础上,再学习一些面向对象的语法

    2 类和对象

    2.1 类和对象的概念

    对象是面向对象编程的两个核心概念

    2.1.1 类

    • 类是对一群具有相同特征或者行为的事物的一统称,是抽象的,不能直接使用
      • 特征被称为属性
      • 行为被称为方法
    • 类就相当于制造飞机时的图纸,是一个模板,是负责创建对象的

    2.1.2 对象

    • 对象是由类创建出来的一个具体存在,可以直接使用
    • 由哪一个类创建出来的对象,就拥有在哪一个类中定义的属性和方法
    • 对象就相当于用图纸制造的飞机

    在程序开发中,应该现有类,再有对象

    2.2 类和对象的关系

    • 类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象
    • 类只有一个,而对象可以有很多个
      • 不同的对象之间属性可能会各不相同
    • 类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多,也不可能少

    2.3 类的设计

    在使用面向对象开发前,应该首先分析需求,确定以下程序中需要包含那些类
    以植物大战僵尸游戏为例分析类的设计如下图
    在这里插入图片描述
    在程序开发中,要设计一个类,通常需要满足以下三个要素

    1. 类名:这类事物的名字,满足大驼峰命名法
    2. 属性:这类事物具有什么样的特征
    3. 方法:这类事物具有什么样的行为

    2.3.1 类名的确定

    名词提炼法:分析整个业务流程,出现的名词,通常就是找到的类

    2.3.2 属性和方法的确定

    • 对对象的特征描述,通常可以定义成属性
    • 对象具有的行为(动词),通常可以定义成方法

    3 面向对象基础语法

    3.1 dir内置函数

    ipython中快速确认某个东西是对象的方法:
    1.在标识符/数据后输一个.,然后按下TAB键,ipython会提示该对象能够调用的方法列表(只能看到一些常用的方法列表)
    2.使用内置函数dir传入标识符/数据,可以查看对象内的所有属性及方法

    在这里插入图片描述
    提示:__方法名__格式的方法是Python提供的内置方法/属性,以下是一些常用的内置方法/属性

    序号方法名类型作用
    01__new__方法创建对象时,会被自动调用
    02__init__方法对象被初始化时,会被自动调用
    03__del__方法对象从内存被销毁前,会被自动调用
    04__str__方法返回对象的描述信息,print函数输出使用

    3.2 定义简单的类(只包含方法)

    3.2.1 定义只包含方法的类

    语法格式

    class 类名:
        def 方法1(self,参数列表):
            pass
            
        def 方法2(self,参数列表):
            pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 方法的定义格式和之前学习过的函数几乎一样
    • 区别在于第一个参数必须是self

    3.2.2 创建对象

    语法格式

    对象变量 = 类名()
    
    • 1

    3.2.3 第一个面向对象程序

    需求
    小猫鱼,小猫

    分析

    1. 定义一个猫类Cat
    2. 定义两个方法eatdrink
    3. 按照需求——不需要定义属性
      在这里插入图片描述
      示例
    # 创建猫类
    class Cat:
        def eat(self):
            print("小猫爱吃鱼")
    
        def drink(self):
            print("小猫要喝水")
    
    # 创建一个对象
    Tom = Cat()
    
    Tom.drink()
    Tom.eat()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果
    在这里插入图片描述

    引用概念的强调

    在面向对象开发中,引用的概念是同样适用的!

    • 在python中使用类创建对象之后,tom变量中仍然记录的是对象在内存中的地址
    • 也就是tom变量引用了新建的猫对象
    • 使用print输出对象变量,默认情况下,是能够输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址

    提示:在计算机中,通常使用十六进制表示内存地址

    • %d可以以10进制输出数字
    • %x可以以16进制输出数字

    在这里插入图片描述

    3.3 方法中的self参数

    3.3.1 案例改造——类的外部给对象增加属性

    • 在Python中,要给对象设置属性,非常的容易,但是不推荐使用,因为对象属性的封装应该封装在类的内部
    • 只需要在类的外部代码中直接通过.设置一个属性即可

    以上一节中的代码为例,在创建了小猫对象Tom = Cat()之后,想要从类外部给Tom增加一个姓名属性,可以直接在执行代码出输入Tom.name = "Tom"即可

    3.3.2 使用self在方法内部输出每一只猫的名字

    想要在类内部调用某个属性,可以直接self.属性名

    哪一个对象调用的方法,self就是哪一个对象的引用。self类似C++里面的this指针

    • 在类封装的方法内部,self就表示当前调用方法的对象自己
    • 调用方法时,程序员不需要传递self函数
    • 在方法内部
      • 可以通过self.访问对象的属性
      • 也可以通过 self.调用其他的对象方法

    示例

    # 创建猫类
    class Cat:
        def eat(self):
            print("%s 爱吃鱼" % self.name)
    
        def drink(self):
            print("%s 要喝水" % self.name)
    
    # 创建一个对象
    Tom = Cat()
    
    Tom.name = "Tom"
    
    Tom.drink()
    Tom.eat()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果
    在这里插入图片描述

    3.4 初始化方法

    3.4.1 之前代码存在的问题——在类的外部给对象增加属性

    在这里插入图片描述

    执行上述程序解释器会报错,因为在执行eat()drink()方法的时候还没有name属性

    3.4.2 初始化方法

    • 当使用类名()创建对象时,会自动执行以下操作:
      • 为对象在内存中分配空间——创建对象
      • 为对象的属性设置初始值——初始化方法(init)
    • 这个初始化方法就是__init__方法,__init__是对象的内置方法

    __init__方法是专门用来定义一个类具有那些属性的方法

    3.4.3 在初始化方法内部定义属性

    • __init__方法内部使用self.属性名=属性的初始值就可以定义属性
    • 定义属性之后,再使用Cat类创建的对象,都会拥有该属性

    示例

    # 创建猫类
    class Cat:
        def __init__(self):
            self.name = "Jerry"
    
        def eat(self):
            print("%s 爱吃鱼" % self.name)
    
        def drink(self):
            print("%s 要喝水" % self.name)
    
    # 创建一个对象
    Tom = Cat()
    
    
    Tom.drink()
    Tom.eat()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    结果
    在这里插入图片描述

    3.4.4 改造初始化方法——初始化的同时设置初始值

    • 在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对__init__方法进行改造
      • 把希望设置的属性值,定义成__init__方法的参数
      • 在方法内部使用self.属性=形参接受外部传递的参数
      • 在创建对象时,使用类名(属性1, 属性2...)调用

    示例

    # 创建猫类
    class Cat:
        def __init__(self, name_):
            self.name = name_
    
        def eat(self):
            print("%s 爱吃鱼" % self.name)
    
        def drink(self):
            print("%s 要喝水" % self.name)
    
    # 创建一个对象
    Tom = Cat("汤姆")
    Tom.drink()
    Tom.eat()
    
    lazy_cat = Cat("大懒猫")
    lazy_cat.drink()
    lazy_cat.eat()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    结果
    在这里插入图片描述

    3.5 内置方法和属性

    序号方法名类型作用
    01__del__方法对象被从内存中销毁前,会被自动调用
    02__str__返回对象的描述信息,print函数输出使用

    3.5.1 __del__方法(类似析构函数)

    • 在Python中
      • 当使用类名()创建对象时,为对象分配空间后,自动调用__init__方法
      • 当一个对象被从内存中销毁前,会自动调用__del__方法
    • 应用场景
      • __init__改造初始化方法,可以让创建对象更加灵活
      • __del__如果希望在对象销毁前,再做一些事情,可以考虑以下该方法
    • 生命周期
      • 一个对象从调用类名()创建,生命周期开始
      • 一个对象的__del__方法一旦被调用,生命周期结束
      • 再对象的生命周期内,可以访问对象属性,或者让对象调用方法

    示例

    # 创建猫类
    class Cat:
        def __init__(self, name):
            self.name_ = name
    
            print("%s 来了" % self.name_)
    
        # 定义析构函数
        def __del__(self):
    
            print("%s 走了" % self.name_)
    
    # 创建一个对象
    tom = Cat("Tom")
    
    print(tom.name_)
    
    print("-" * 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果
    在这里插入图片描述
    分析
    tom是一个全局变量,只有在整个程序结束之后才会被销毁,因此会先打印----------,在执行析构函数中的语句

    Python中有一个关键字del,可以直接销毁变量,若在打印-------之前销毁tom变量,则会先执行析构函数中的语句,代码如下:

    # 创建猫类
    class Cat:
        def __init__(self, name):
            self.name_ = name
    
            print("%s 来了" % self.name_)
    
        # 定义析构函数
        def __del__(self):
    
            print("%s 走了" % self.name_)
    
    # 创建一个对象
    tom = Cat("Tom")
    
    print(tom.name_)
    
    del(tom)
    
    print("-" * 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    结果:
    在这里插入图片描述

    3.5.2 __str__方法

    • 在Python中,使用print输出对象变量,默认情况下,会输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制表示)[见3.2.3]
    • 如果在开发中,希望使用print输出对象变量时能够打印自定义的内容,就可以利用__str__这个内置方法了

    注意:__str__方法必须返回一个字符串

    # 创建猫类
    class Cat:
        def __init__(self, name):
            self.name_ = name
    
            print("%s 来了" % self.name_)
    
        # 定义析构函数
        def __del__(self):
    
            print("%s 走了" % self.name_)
    
        def __str__(self):
            # 必须返回一个字符串
            return "我是小猫 %s" % self.name_
    
    # 创建一个对象
    tom = Cat("Tom")
    
    print(tom)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    如上例,在使用print函数直接打印对象tom时,输出了__str__中返回的内容

    4 面向对象封装案例

    4.1 封装

    1. 封装时面向对象编程的一大特点
    2. 面向对象编程的第一步 —— 将属性方法封装到一个抽象的
    3. 外界使用类创建对象,然后让对象调用方法
    4. 对象方法的细节都被封装在类的内部

    4.2 小明爱跑步

    需求

    1. 小明 体重75.0公斤
    2. 小明每次跑步会减肥0.5公斤
    3. 小明每次吃东西体重会增加1公斤

    在这里插入图片描述
    示例

    class Person:
        def __init__(self, name, weight) -> None:
            self.name_ = name
            self.weight_ = weight
    
        def __str__(self) -> str:
            return "我的名字是 %s,我的体重是 %.2f 公斤" % (self.name_, self.weight_)
    
        def run(self):
            print("跑步好,跑步减肥")
            self.weight_ -= 0.5
    
        def eat(self):
            print("没吃饱哪有力气减肥")
            self.weight_ += 1
    
    xiaoming = Person("小明", 75.0)
    
    xiaoming.eat()
    xiaoming.run()
    
    print(xiaoming)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    结果
    在这里插入图片描述

    4.2.1 小明爱跑步扩展——小美也爱跑步

    需求

    1. 小明和小美都爱跑步
    2. 小明体重75.0公斤
    3. 小美体重45.0公斤
    4. 每次跑步都会减少0.5公斤
    5. 每次吃东西都会增加1公斤

    示例

    class Person:
        def __init__(self, name, weight) -> None:
            self.name_ = name
            self.weight_ = weight
    
        def __str__(self) -> str:
            return "我的名字是 %s,我的体重是 %.2f 公斤" % (self.name_, self.weight_)
    
        def run(self):
            print("跑步好,跑步减肥")
            self.weight_ -= 0.5
    
        def eat(self):
            print("没吃饱哪有力气减肥")
            self.weight_ += 1
    
    xiaoming = Person("小明", 75.0)
    
    xiaoming.eat()
    xiaoming.run()
    
    print(xiaoming)
    
    xiaomei = Person("小美", 45.0)
    
    xiaomei.eat()
    xiaomei.run()
    
    print(xiaomei)
    
    • 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

    结果
    在这里插入图片描述

    4.3 摆放家具

    需求

    1. 房子(House)有户型总面积家具名称列表
      • 新房子中没有任何的家具
    2. 家具(HouseItem)有名字占地面积,其中
      • 席梦思(bed)占地4平米
      • 衣柜(chest)占地2平米
      • 餐桌(table)占地1.5平米
    3. 将以上三件家具添加到房子中
    4. 打印房子时,要求输出户型、总面积、剩余面积、家具名称列表

    在这里插入图片描述

  • 相关阅读:
    Win11如何开启移动中心页面的操作方法教学
    POJ 2104 K-th Number 平方分割(分桶法)
    Android JetPack Compose+Room----实现搜索记录功能
    云端日历同步大师:iCloud让工作与生活井井有条
    OpenCV自学笔记十七:傅里叶变换
    批量取redis keyvalue和批量删除key
    SuperMap GIS管线数据优化
    02-Nginx安装与常用命令
    八、数据类型转换
    WPF自定义控件与样式(13)-自定义窗体Window & 自适应内容大小消息框MessageBox
  • 原文地址:https://blog.csdn.net/dreautumn/article/details/126330454