Python基础-03
学习目标
- 理解面向对象
- 类和对象
- 添加和获取对象属性
- 魔法方法
理解面向对象
- 面向对象是一种抽象化的编程思想,很多编程语⾔言中都有的一种思想。
- 例如:洗衣服
- 思考:几种途径可以完成洗衣服?
- 答: 手洗 和 机洗。
- 手洗:找盆 - 放水 - 加洗衣粉 - 浸泡 - 搓洗 - 拧干水 - 倒水 - 漂洗N次 - 拧干 - 晾晒。
- 机洗:打开洗衣机 - 放衣服 - 加洗衣粉 - 按下开始按钮 - 晾晒。
- 答: 手洗 和 机洗。
- 思考:对⽐比两种洗衣服途径,同学们发现了什么?
- 答:机洗更简单
- 思考:机洗,只需要找到一台洗衣机,加入简单操作就可以完成洗衣服的工作,而不需要关心洗衣机内部发生了什么事情。
- 总结:面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。
类和对象
- 思考:洗衣机洗衣服描述过程中,洗衣机其实就是一个事物,即对象,洗衣机对象哪来的呢?
- 答:洗衣机是由工厂工人制作出来。
- 思考:工厂工人怎么制作出的洗衣机?
- 答:工人根据设计师设计的功能图纸制作洗衣机。
- 总结:图纸 → 洗衣机 → 洗衣服。
- 在面向对象编程过程中,有两个重要组成部分:类 和 对象。
- 类和对象的关系:用类去创建一个对象。
理解类和对象
类
- 类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。
- 特征即是属性
- 行为即是方法
- 类⽐比如是制造洗衣机时要用到的图纸,也就是说类是用来创建对象。
对象
- 对象是类创建出来的真实存在的事物,例如:洗衣机。
- 注意:开发中,先有类,再有对象。
面向对象实现方法
定义类
Python2中类分为:经典类 和 新式类
语法
- 注意:类名要满足标识符命名规则,同时遵循⼤大驼峰命名习惯。
1 | class 类名(): |
- 体验
1 | class Washer(): |
- 拓展:经典类
- 不由任意内置类型派生出的类,称之为经典类
1 | class 类名: |
创建对象
- 对象又名实例。
- 语法
1 | 对象名 = 类名() |
- 体验
- 注意:创建对象的过程也叫实例化对象
1 | # 创建对象 |
self
- self指的是调用该函数的对象。
1 | # 1. 定义类 |
- 注意:打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。
添加和获取对象属性
- 属性即是特征,⽐比如:洗衣机的宽度、高度、重量…
- 对象属性既可以在类外面添加和获取,也能在类里面添加和获取。
类外面添加对象属性
- 语法
1 | 对象名.属性名 = 值 |
- 体验
1 | haier1.width = 500 |
类外面获取对象属性
- 语法
1 | 对象名.属性名 |
- 体验
1 | print(f'haier1洗衣机的宽度是{haier1.width}') |
类里面获取对象属性
- 语法
1 | self.属性名 |
- 体验
1 | # 定义类 |
魔法方法
- 在Python中,
__xx__()
的函数叫做魔法方法,指的是具有特殊功能的函数。
_ _ init _ _()
体验_ _ init _ _()
思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?
答:理应如此。
__init__()
方法的作用:初始化对象。
1 | class Washer(): |
- 注意:
__init__()
方法,在创建一个对象时默认被调用,不需要手动调用__init__(self)
中的self参数,不需要开发者传递,python解释器器会自动把当前的对象引用传递过去。
带参数的_ _ init _ _()
- 思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
- 答:传参数。
1 | class Washer(): |
_ _ str _ _()
- 当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了
__str__
方法,那么就会打印从在这个方法中 return 的数据。
1 | class Washer(): |
_ _del _ _()
- 当删除对象时,python解释器器也会默认调用
__del__()
方法。
1 | class Washer(): |
综合应用
烤地瓜
需求
- 需求主线:
- 被烤的时间和对应的地瓜状态:
- 0-3分钟:生的
- 3-5分钟:半生不熟
- 5-8分钟:熟的
- 超过8分钟:烤糊了
- 添加的调料:
- 用户可以按自己的意愿添加调料
- 被烤的时间和对应的地瓜状态:
步骤分析
需求涉及一个事物: 地瓜,故案例涉及一个类:地瓜类。
定义类
- 地瓜的属性
- 被烤的时间
- 地瓜的状态
- 添加的调料
- 地瓜的方法
- 被烤
- 用户根据意愿设定每次烤地瓜的时间
- 判断地瓜被烤的总时间是在哪个区间,修改地瓜状态
- 添加调料
- 用户根据意愿设定添加的调料
- 将用户添加的调料存储
- 被烤
- 显示对象信息
- 地瓜的属性
创建对象,调用相关实例方法
代码实现
- 定义类
- 地瓜属性
- 定义地瓜初始化属性,后期根据程序推进更新实例属性
- 地瓜属性
1 | class SweetPotato(): |
定义烤地瓜方法
1 | class SweetPotato(): |
输出对象状态
1 | class SweetPotato(): |
测试实例属性和实例方法
1 | digua1 = SweetPotato() |
定义调料方法,并调用该方法
1 | class SweetPotato(): |
代码总览
1 | # 定义类 |
搬家具
需求
- 将小于房子剩余面积的家具摆放到房子中
步骤分析
需求涉及两个事物:房子 和 家具,故被案例涉及两个类:房子类 和 家具类。
定义类
- 房子类
- 实例属性
- 房子地理位置
- 房子占地面积
- 房子剩余面积
- 房子内家具列表
- 实例方法
- 容纳家具
- 显示房屋信息
- 实例属性
- 家具类
- 家具名称
- 家具占地面积
- 房子类
创建对象并调用相关方法
代码实现
- 定义家具类
1 | class Furniture(): |
- 房子类
1 | class Home(): |
创建对象并调用实例属性和方法
1 | bed = Furniture('双人床', 6) |
总结
- 面向对象重要组成部分
- 类
- 创建类
1 | class 类名(): |
- 对象
1 | 对象名 = 类名() |
- 添加对象属性
1 | # 类外面 |
- 获取对象属性
1 | # 类外面 |
魔法方法
__init__()
: 初始化__str__()
:输出对象信息__del__()
:删除对象时调用
继承
学习目标
- 继承的概念
- 单继承
- 多继承
- 子类重写父类的同名属性和方法
- 子类调用父类的同名属性和方法
- 多层继承
- super()
- 私有属性和私有方法
继承的概念
- 生活中的继承,一般指的是子⼥女女继承父辈的财产。
- 拓展1:经典类或旧式类
- 不由任意内置类型派生出的类,称之为经典类。
1 | class 类名: |
- 拓展2:新式类
1 | class 类名(object): |
- Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:
1 | # 父类A |
- 在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
单继承
- 故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师父要把这套技术传授给他的唯一的最得意的徒弟。
- 分析:徒弟是不是要继承师父的所有技术?
1 | # 1. 师父类 |
多继承
故事推进:daqiu是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,在百度搜索到⿊黑⻢马程序员,报班学习煎饼果子技术。
所谓多继承意思就是一个类同时继承了多个父类。
1 | class Master(object): |
- 注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
子类重写父类同名方法和属性
- 故事:daqiu掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。
1 | class Master(object): |
- 子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
子类调用父类同名方法和属性
- 故事:很多顾客都希望也能吃到古法和⿊黑⻢马的技术的煎饼果子。
1 | class Master(object): |
多层继承
- 故事:N年后,daqiu老了,想要把所有技术传承给自己的徒弟。
1 | class Master(object): |
super()调用父类方法
1 | class Master(object): |
- 注意:使用super() 可以自动查找父类。调用顺序遵循 mro 类属性的顺序。⽐比较适合单继承使用。
私有权限
定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
故事:daqiu把技术传承给徒弟的同时,不想把自己的钱(2000000个亿)继承给徒弟,这个时候就要为钱这个实例属性设置私有权限。
设置私有权限的方法:在属性名和方法名 前面 加上两个下划线
__
。
1 | class Master(object): |
- 注意:私有属性和私有方法只能在类里面访问和修改。
获取和修改私有属性值
- 在Python中,一般定义函数名
get_xx
用来获取私有属性,定义set_xx
用来修改私有属性值。
1 | class Master(object): |
总结
- 继承的特点
- 子类默认拥有父类的所有属性和方法
- 子类重写父类同名方法和属性
- 子类调用父类同名方法和属性
- super()方法快速调用父类方法
- 私有权限
- 不能继承给子类的属性和方法需要添加私有权限
- 语法
1 | class 类名(): |
三大特性与方法
学习目标
- 面向对象三⼤大特性
- 类属性和实例属性
- 类方法和静态方法
面向对象三⼤大特性
- 封装
- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
- 继承
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
- 多态
- 传入不同的对象,产生不同的结果
多态
了解多态
- 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
- 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处:调用灵活,有了多态,更容易易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
- 实现步骤:
- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
体验多态
1 | class Dog(object): |
类属性和实例属性
类属性
设置和访问类属性
- 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
- 类属性可以使用 类对象 或 实例对象 访问。
1 | class Dog(object): |
- 类属性的优点
- 记录的某项数据 始终保持一致时,则定义类属性。
- 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有,仅占用一份内存,更加节省内存空间。
修改类属性
- 类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
1 | class Dog(object): |
实例属性
1 | class Dog(object): |
类方法和静态方法
类方法
类方法特点
- 需要用装饰器器
@classmethod
来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以 cls 作为第一个参数。
类方法使用场景
- 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
- 类方法一般和类属性配合使用
1 | class Dog(object): |
静态方法
静态方法特点
- 需要通过装饰器器
@staticmethod
来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。 - 静态方法 也能够通过 实例对象 和 类对象 去访问。
静态方法使用场景
- 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利利于 减少不必要的内存占用和性能消耗
1 | class Dog(object): |
总结
- 面向对象三⼤大特性
- 封装
- 继承
- 多态
- 类属性
- 归属于类对象的属性,所有对象共有的属性
- 实例属性
- 类方法
1 |
|
- 静态方法
1 |
|
异常
学习目标
- 了解异常
- 捕获异常
- 异常的else
- 异常finally
- 异常的传递
- 自定义异常
了解异常
- 当检测到一个错误时,解释器器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的”异常”。
- 例如:以
r
方式打开一个不存在的文件。
1 | open('test.txt', 'r') |
异常的写法
语法
1 | try: |
快速体验
- 需求:尝试以
r
模式打开文件,如果文件不存在,则以w
方式打开。
1 | try: |
捕获指定异常
语法
1 | try: |
体验
1 | try: |
- 注意:
如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
一般try下方只放一行尝试执行的代码。
捕获多个指定异常
- 当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
1 | try: |
捕获异常描述信息
1 | try: |
捕获所有异常
- Exception是所有程序异常类的父类。
1 | try: |
异常的else
- else表示的是如果没有异常要执行的代码。
1 | try: |
异常的finally
- finally表示的是无论是否异常都要执行的代码,例如关闭文件。
1 | try: |
异常的传递
体验异常传递
需求:
尝试只读方式打开test.txt文件,如果文件存在则读取文件内容,文件不存在则提示用户即可。
读取内容要求:尝试循环读取内容,读取过程中如果检测到用户意外终⽌止程序,则except 捕获异常并提示用户。
1 | import time |
自定义异常
- 在Python中,抛出自定义异常的语法为raise 异常类对象。
- 需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则报错,即抛出自定义异常,并捕获该异常)。
1 | # 自定义异常类,继承Exception |
总结
异常语法
1 | try: |
捕获异常
1 | except 异常类型: |
自定义异常
1 | # 1. 自定义异常类 |
模块和包
学习目标
- 了解模块
- 导入模块
- 制作模块
__all__
- 包的使用方法
模块
- Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。
- 模块能定义函数,类和变量,模块里也能包含可执行的代码。
导入模块
导入模块的方式
- import 模块名
- from 模块名 import 功能名
- from 模块名 import *
- import 模块名 as 别名
- from 模块名 import 功能名 as 别名
导入方式详解
import
- 语法
1 | # 1. 导入模块 |
- 体验
1 | import math |
from..import..
- 语法
1 | from 模块名 import 功能1, 功能2, 功能3... |
- 体验
1 | from math import sqrt |
from .. import *
- 语法:
1 | from 模块名 import * |
- 体验
1 | from math import * |
as定义别名
- 语法
1 | # 模块定义别名 |
- 体验
1 | # 模块别名 |
制作模块
- 在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。
定义模块
- 新建一个Python文件,命名为 my_module1.py ,并定义 testA 函数。
1 | def testA(a, b): |
测试模块
- 在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息.,例如,在my_module1.py 文件中添加测试代码。
1 | def testA(a, b): |
- 此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行testA 函数的调用。
- 解决办法如下:
1 | def testA(a, b): |
调用模块
1 | import my_module1 |
注意事项
如果使用
from .. import ..
或from .. import *
导入多个模块的时候,且模块内有同名功能。当调用这个同名功能的时候,调用到的是后面导入的模块的功能。体验
1 | # 模块1代码 |
模块定位顺序
当导入一个模块,Python解析器器对模块位置的搜索顺序是:
当前目录
如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
- 注意
- 自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
- 使用 from 模块名 import 功能的时候,如果功能名字重复,调用到的是最后定义或导入的功能。
_ _ all _ _
- 如果一个模块文件中有
__all__
变量,当使用from xxx import *
导入时,只能导入这个列表中的元素。 - my_module1模块代码
1 | __all__ = ['testA'] |
- 导入模块的文件代码
1 | from my_module1 import * |
包
- 包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为
__init__.py
文件,那么这个文件夹就称之为包。
制作包
- [New] — [Python Package] — 输入包名 — [OK] — 新建功能模块(有联系的模块)。
- 注意:新建包后,包内部会自动创建
__init__.py
文件,这个文件控制着包的导入行为。
快速体验
- 新建包mypackage
- 新建包内模块: my_module1 和 my_module2
- 模块内代码如下
1 | # my_module1 |
1 | # my_module2 |
导入包
方法一
1 | import 包名.模块名 |
- 体验
1 | import my_package.my_module1 |
方法二
- 注意:必须在
__init__.py
文件中添加__all__ = []
,控制允许导入的模块列表。
1 | from 包名 import * |
- 体验
1 | from my_package import * |
总结
- 导入模块方法
1 | import 模块名 |
- 导入包
1 | import 包名.模块名 |
__all__ = []
:允许导入的模块或功能列表
面向对象版学员管理系统
学习目标
- 了解面向对象开发过程中类内部功能的分析方法
- 了解常用系统功能
- 添加
- 删除
- 修改
- 查询
系统需求
- 使用面向对象编程思想完成学员管理系统的开发,具体如下:
- 系统要求:学员数据存储在文件中
- 系统功能:添加学员、删除学员、修改学员信息、查询学员信息、显示所有学员信息、保存学员信息及退出系统等功能。
准备程序文件
分析
- ⻆角⾊色分析
- 学员
- 管理系统
- 工作中注意事项
- 为了方便便维护代码,一般一个⻆角⾊色一个程序文件;
- 项目要有主程序入口,习惯为main.py
创建程序文件
创建项目目录,例如: StudentManagerSystem
程序文件如下:
- 程序入口文件:main.py
- 学员文件:student.py
- 管理系统文件:managerSystem.py
书写程序
student.py
需求:
- 学员信息包含:姓名、性别、手机号;
- 添加
__str__
魔法方法,方便便查看学员对象信息
程序代码
1 | class Student(object): |
managerSystem.py
需求:
- 存储数据的位置:文件(student.data)
- 加载文件数据
- 修改数据后保存到文件
- 存储数据的形式:列表存储学员对象
- 系统功能
- 添加学员
- 删除学员
- 修改学员
- 查询学员信息
- 显示所有学员信息
- 保存学员信息
- 退出系统
- 存储数据的位置:文件(student.data)
定义类:
1 | class StudentManager(object): |
- 管理系统框架
- 需求:系统功能循环使用,用户输入不同的功能序号执行不同的功能。
- 步骤
- 定义程序入口函数
- 加载数据
- 显示功能菜单
- 用户输入功能序号
- 根据用户输入的功能序号执行不同的功能
- 定义系统功能函数,添加、删除学员等
- 定义程序入口函数
1 | class StudentManager(object): |
main.py
1 | # 1. 导入managerSystem模块 |
定义系统功能函数
添加功能
- 需求:用户输入学员姓名、性别、手机号,将学员添加到系统。
- 步骤
- 用户输入姓名、性别、手机号
- 创建该学员对象
- 将该学员对象添加到列表
- 代码
1 | # 添加学员函数内部需要创建学员对象,故先导入student模块 |
删除学员
- 需求:用户输入目标学员姓名,如果学员存在则删除该学员。
- 步骤
- 用户输入目标学员姓名
- 遍历学员数据列表,如果用户输入的学员姓名存在则删除,否则提示该学员不存在。
- 代码
1 | # 2.3 删除学员:删除指定姓名的学员 |
修改学员信息
- 需求:用户输入目标学员姓名,如果学员存在则修改该学员信息。
- 步骤
- 用户输入目标学员姓名;
- 遍历学员数据列表,如果用户输入的学员姓名存在则修改学员的姓名、性别、手机号数据,否则提示该学员不存在。
- 代码
1 | # 2.4 修改学员信息 |
查询学员信息
- 需求:用户输入目标学员姓名,如果学员存在则打印该学员信息
- 步骤
- 用户输入目标学员姓名
- 遍历学员数据列表,如果用户输入的学员姓名存在则打印学员信息,否则提示该学员不存在。
- 代码
1 | # 2.5 查询学员信息 |
显示所有学员信息
- 打印所有学员信息
- 步骤
- 遍历学员数据列表,打印所有学员信息
- 代码
1 | # 2.6 显示所有学员信息 |
保存学员信息
- 需求:将修改后的学员数据保存到存储数据的文件。
- 步骤
- 打开文件
- 文件写入数据
- 关闭文件
- 思考
- 文件写入的数据是学员对象的内存地址吗?
- 文件内数据要求的数据类型是什么?
- 拓展
__dict__
1 | class A(object): |
- 在Python中
1 | # 2.7 保存学员信息 |
加载学员信息
- 需求:每次进入系统后,修改的数据是文件里面的数据
- 步骤
- 尝试以”r” 模式打开学员数据文件,如果文件不存在则以”w” 模式打开文件
- 如果文件存在则读取数据并存储数据
- 读取数据
- 转换数据类型为列表并转换列表内的字典为对象
- 存储学员数据到学员列表
- 关闭文件
- 代码
1 | # 2.8 加载学员信息 |
总结
- 函数
- 定义和调用
- 参数的使用
- 面向对象
- 定义类
- 创建对象
- 定义和调用实例属性
- 定义和调用实例方法
- 数据类型
- 列表
- 增加删除数据
- 列表推导式
- 字典
- 字符串
- 列表
- 文件操作
- 打开文件
- 读取或写入
- 关闭文件
- 感谢你赐予我前进的力量