《python编程:从入门到实战》学习笔记
文章目录
- 第二章:变量和简单数据类型
- 2.1 变量的命名
- 2.2 字符串
- 2.2.1 修改字符串大小写
- 2.2.2 在字符串中使用变量
- 2.2.3 制表符、换行符
- 2.2.4 删除空白
- 2.3 数
- 2.3.1 整数
- 2.3.2 浮点数
- 2.3.3 数中的下划线
- 2.3.4 常量
- 第三章 列表
- 3.1 列表
- 3.1.1 访问列表中的元素
- 3.1.2 列表中元素的使用
- 3.2 修改、添加、删除列表元素
- 3.2.1 修改列表
- 3.2.2 添加元素
- 3.2.3 删除元素
- 3.3 组织列表
- 3.3.1 sort() 对列表永久排序
- 3.3.2 sorted() 对列表临时排序
- 3.3.3 获取列表长度
- 第四章 操作列表
- 4.1 遍历列表
- 4.1.1 在for循环中执行更多操作
- 4.1.2 在for循环结束后的操作
- 4.2 避免缩进错误
- 4.3 创建数值列表
- 4.3.1 使用函数 range()
- 4.3.2 使用range()函数直接创建列表
- 4.3.3 对数字列表进行简单的统计计算
- 4.3.4 列表解析式
- 4.4 列表的切片
- 4.4.1 切片
- 4.4.2 遍历切片
- 4.4.3 复制列表
- 4.5 元组
- 4.5.1 定义元组
- 4.5.2 元组的遍历
- 4.5.3 修改元组变量
- 第五章 if 语句
- 5.1 一个简单的示例
- 5.2 条件测试
- 5.2.1 检查是否相等
- 5.2.2 检查是否相等时忽略大小写
- 5.2.3 检查是否不相等
- 5.2.4 数值的比较
- 5.2.5 检查多个条件
- 5.2.6 检查特定值是否在列表中
- 5.2.7 检查特定值是否不在列表中
- 5.2.8 布尔表达式
- 5.3 if 语句
- 5.3.1 简单的if语句
- 5.3.2 if-else语句
- 5.3.3 if - elif - else结构
- 5.3.4 使用多个elif 代码块
- 5.3.5 省略else代码块
- 5.3.6 测试多个条件
- 5.4 使用 if 语句处理列表
- 5.4.1 检查特殊元素
- 5.4.2 确定列表不是空的
- 5.5 设置 if 语句的格式
- 第六章 字典
- 6.1 一个简单的字典
- 6.2 使用字典
- 6.2.1 访问字典中的值
- 6.2.2 添加键值对
- 6.2.3 先创建一个空字典
- 6.2.4 修改字典中的值
- 6.2.5 删除键值对
- 6.2.6 使用 get()来访问值
- 6.3 遍历字典
- 6.3.1 遍历键值对:
- 6.3.2 遍历字典中的键
- 6.3.3 按特定顺序遍历字典中的键
- 6.3.4 遍历字典中的所有值
- 6.4 嵌套
- 6.4.1 字典列表
- 6.4.2 在字典中存储列表
- 6.4.3 在字典中存储字典
- 第七章 用户输入和 while 循环
- 7.1 函数 input()原理
- 7.1.1 编写清晰的程序
- 7.1 .2 使用input()函数获取数值输入
- 7.2 while 循环简介
- 7.2.1 使用 while 循环
- 7.2.2 使用标志
- 7.2.3 使用 break 退出循环
- 7.2.4 在循环中使用continue
- 7.3 使用 while 循环处理列表和字典
- 7.3.1 在列表之间移动元素
- 7.3.2 删除列表中特定值
- 第八章 函数
- 8.1 定义函数
- 8.1.1 向函数传递信息
- 8.1.2 实参和形参
- 8.2 传递实参
- 8.2.1 位置实参
- 8.2.2 关键字实参
- 8.2.3 默认值
- 8.3 返回值
- 8.3.1 返回简单值
- 8.3.2 让实参可选
- 8.3.3 返回字典
- 8.4 传递列表
- 8.5 传递任意数量的实参
- 8.5.1 结合位置实参和任意数量实参
- 8.5.2 使用任意数量的关键字实参
- 8.6 将函数存储在模块中
- 8.6.1 导入整个模块
- 8.6.2 导入特定的函数
- 8.6.3 使用 as 给函数指定别名
- 8.6.4 使用 as 给模块指定别名
- 8.6.5 导入模块中的所有函数
- 第九章 类
- 9.1 创建和使用类
- 9.1.1 创建 Dog 类
- 9.1.2 根据类创建实例
- 9.2 使用类和实例
- 9.2.1 Car 类
- 9.2.2 给属性指定默认值
- 9.2.3 修改属性的值
- 9.3 继承
- 9.3.1 子类的方法 __ init __()
- 9.3.2 给子类定义属性和方法
- 9.3.3 重写父类的方法
- 9.3.4 将实例用作属性
- 9.4 导入类
- 9.4.1 导入单个类
- 9.4.2 在一个模块中存储多个类
- 9.4.3 从一个模块中导入多个类
- 9.4.4 导入整个模块
- 9.4.5 导入模块中的所有类
- 9.4.6 在一个模块中导入另一个模块
- 9.4.7 使用别名
- 9.5 python 标准库
- 第十章 文件和异常
- 10.1 从文件中读取数据
- 10.1.1 读取整个文件
- 10.1.2 文件路径
- 10.1.3 逐行读取
- 10.1.4 创建一个包含文件各行内容的列表
- 10.2 写入文件
- 10.2.1 写入空文件
- 10.2.2 写入多行文件
- 10.2.3 附加到文件
- 10.3 异常
- 10.3.1 处理 ZeroDivisionError 异常
- 10.3.2 使用 try - except 模块
- 10.3.3 使用异常避免崩溃
- 10.3.4 else 代码块
- 10.3.5 处理 FileNotFoundError 异常
- 10.3.6 静默失败
- 10.4 存储数据
- 10.4.1 使用 json.dump() 和 json.load()
- 第 11 章 测试代码
- 11.1 测试函数
- 11.1.1 单元测试和测试用例
- 11.1.2 可通过的测试
第二章:变量和简单数据类型
2.1 变量的命名
- 变量名只能包含数字、字母、下划线
- 变量名可以以字母或下划线开头,但不能以数字开头
- 变量名中不能有空格
- 变量名不能和python中的关键词一致
- 变量名应简单、具有描述性
name = "xiao hong" # name 就是一个变量
name_student = "xiao hong" # name_student 也是一个变量2name = "xiao hong" # 是错误的写法,数字不能放在变量的开头
2.2 字符串
在Python中,字符串就是一串用引号括起来的字符串,注意单引号、双引号都可以!
"This is string" # 双引号、单引号都可以表示一个字符串
'This is string'
2.2.1 修改字符串大小写
操作符 | 解释 |
---|---|
title() | 将单词首字母变为大写 |
upper() | 将单词变为大写 |
lower() | 将单词变为小写 |
name = "xiao hong"print(name.title())
print(name.upper())
print(name.lower())输出:
Xiao Hong
XIAO HONG
xiao hong
2.2.2 在字符串中使用变量
有时,我们需要将变量赋值给字符串,python中具体操作是:str = f"{变量名}" 或 str = “{}”.format(变量名)
举例看看就懂:
name_1 = "xiao hong" # name_1 是变量
name_2 = "li gang" # name_2 是变量
student = f"{name_1} and {name_2} are students" # student 中的字符串包含上面两个变量的值
print(student) 输出:
xiao hong and li gang are students
或者:
student = "{} and {} are students".format(name_1, name_2)
print(student) 输出:
xiao hong and li gang are students
2.2.3 制表符、换行符
制表符:\t
print("\tpython") # 输出字符串会缩进输出:python
换行符:\n
print("\npython") # 输出字符串会在下一行输出输出:python
制表符、换行符一起使用:
print("\npython") # 输出字符串会在下一行缩进输出输出:python
2.2.4 删除空白
对于程序来说,"python"和"python "是不一样的,因为后者中包含空格,但有些场景我们认为他们是一致的,这时我们就应该将他们做一些处理,删除其中的空格!
操作符 | 解释 |
---|---|
strip() | 删除左右两边的空格 |
rstrip() | 删除右边的空格 |
lstrip() | 删除左边的空格 |
举例看看:
language = " python " # 左右都有空格
print(language.strip()) # 删除左右空格
print(language.rstrip()) # 删除右边空格
print(language.lstrip()) # 删除左边空格输出:
pythonpython
python
2.3 数
2.3.1 整数
python中整数的操作:(+)加、(-)减、(*)乘、(/)除、(//)整除、(**)乘方、(%)取余
具体举例看看就懂:
print(1 + 2) # 加
print(2 - 1) # 减
print(2 * 3) # 乘
print(3 / 2) # 除
print(3 // 2) # 整除:3除以2是1.5,再对1.5取整就是1
print(3 ** 2) # 乘方: 这里是3的2次方。同理(3 ** 4)表示:3的4次方,结果是81
print(3 % 2) # 取余:3除以2,余数是1输出:
3
1
6
1.5
1
9
1
注意:空格不影响上面的计算表达式
2.3.2 浮点数
带小数点的数称为浮点数,浮点数的操作和上面一致!注意:任意两个数相除都是浮点数,即是这两个数可以整除,举例看看:
print(4 / 2) # 可以整除,结果也是浮点数!输出:
2.0
2.3.3 数中的下划线
当数字很大时,可以使用下划线,让数字显示的更加清晰明了:
number = 14_000_000_000 # 140亿,这样表示很清晰明了,其中下划线不影响数字的大小、存储等!
print(number) # 打印时,是不会显示下划线的输出:
14000000000注意:
1_000 和 10_00 大小是一样的
2.3.4 常量
常量即在程序运行中大小保持不变。一般使用全部大写来表示常量:
NUMBER = 100 # 一般用这种全部大写的来表示常量!
第三章 列表
3.1 列表
列表是由一系列按特定顺序排列的元素组成!在python中用 [] 表示列表,其中各元素由逗号隔开。
举例看看:
name = ["xiao hong", "li gang"] # name 是一个列表,包含两个元素,元素之间由逗号隔开
print(name)输出:
['xiao hong', 'li gang']
3.1.1 访问列表中的元素
列表中的元素是有序的,我们可以根据元素的位置(索引)找到具体的元素!如:列表名[索引]
注意:python中的索引从0开始,即0表示第一个元素
举例看看就懂:
name = ["xiao hong", "li gang"] # 列表
print(name[0]) # 返回列表第一个元素,索引从0开始
print(name[1]) # 返回列表第二个元素输出:
xiao hong
li gang
如何获取最后的元素呢?
name = ["xiao hong", "li gang"]
print(name[-1]) # -1 表示访问列表中最后一个元素输出:
li gang
同理,倒数第二的元素用-2表示,以此类推!
3.1.2 列表中元素的使用
我们对于获取的元素可以进一步操作,如:
name = ["xiao hong", "li gang"]
print(name[0].title()) # 将第一个元素变为首字母大写的字符串输出:
Xiao Hong
name = ["xiao hong", "li gang"] # 列表
result = f"{name[0]} is a good student" # 将列表元素放入字符串中!
print(result)输出:
xiao hong is a good student
3.2 修改、添加、删除列表元素
我们一般会对创建的列表进行改动,来符合我们想要的列表,包括对列表元素的修改、添加、删除等操作!
3.2.1 修改列表
修改列表中某元素的操作:列表名[索引] = 新值
举例看看就懂:
name = ["xiao hong", "li gang"] # 原始列表
print(name)name[0] = "da zhuang" # 修改第一个元素
print(name)输出:
['xiao hong', 'li gang']
['da zhuang', 'li gang']
我们不仅可以修改第一个元素,同理可以修改任意位置的元素!
3.2.2 添加元素
有时我们需要在列表中添加新的元素,具体操作如下:
- 列表末尾添加元素:列表名.append(元素)
name = ["xiao hong", "li gang"] # 原始列表
print(name)name.append("da zhuang") # 添加元素
print(name)输出:
['xiao hong', 'li gang']
['xiao hong', 'li gang', 'da zhuang']
- 在列表中插入元素:列表名.insert(插入位置,插入元素)
name = ["xiao hong", "li gang"] # 原始列表
print(name)name.insert(1, "da zhaung") # 在第一个位置插入“da zhuang”
print(name)输出:
['xiao hong', 'li gang']
['xiao hong', 'da zhaung', 'li gang']
3.2.3 删除元素
对于不同场景,我们删除元素的方法是不一样的,具体分为:
- 已知要删除元素的索引:del 列表名[索引]
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name) del name[2] # 删除第三个元素
print(name)输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
- 已知要删除元素的值:列表名.remove(元素)
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name)name.remove("da zhuang") # 删除第三个元素
print(name)输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
若列表中出现多个相同元素,remove操作只能删除第一个指定的元素!
以上操作,删除元素后,被删除的元素就找不到了,无法再去访问了,而有时我们需要刚刚删除的元素,这时我们可以弹出要删除的元素
- 弹出要删除的元素:列表名.pop(索引)
name = ["xiao hong", "li gang", "da zhuang"] # 原始列表
print(name)item = name.pop() # 默认弹出最后一个元素,我们也可以指定索引来弹出具体位置的元素
print(name)
print(item)输出:
['xiao hong', 'li gang', 'da zhuang']
['xiao hong', 'li gang']
li gang
通过上面的操作发现,pop 和 del 的作用基本一致,但是del删除元素后就不能再访问该元素了,而pop可以再访问这个元素!
3.3 组织列表
当我们创建好一个列表时!其中元素的顺序可能不是我们想要的,我们可能想升序或降序元素值,那么具体如何操作呢!
3.3.1 sort() 对列表永久排序
我们可以使用sort()方法对列表进行排序:列表名.sort()
- 列表名.sort() : 升序(默认升序)
- 列表名.sort(reverse=True) : 降序
具体举例看看就懂:
age = [23, 18, 19, 20, 22, 18, 20] # 原始列表
print(age) age.sort() # 排序,默认升序
print(age)
age.sort(reverse=True) # 降序
print(age)输出:
[23, 18, 19, 20, 22, 18, 20]
[18, 18, 19, 20, 20, 22, 23]
[23, 22, 20, 20, 19, 18, 18]
3.3.2 sorted() 对列表临时排序
如果我们在排序后,还要保留以前的列表,就应该使用sorted()方法:sorted(列表名)
- sorted(列表名) : 升序(默认升序)
- sorted(列表名, reverse=True) : 降序
age = [23, 18, 19, 20, 22, 18, 20] # 原始列表
print(age)
print(sorted(age)) # 升序后的临时列表
print(sorted(age, reverse=True)) # 降序后的临时列表
print(age) # 原始列表,没有改变输出:
[23, 18, 19, 20, 22, 18, 20]
[18, 18, 19, 20, 20, 22, 23]
[23, 22, 20, 20, 19, 18, 18]
[23, 18, 19, 20, 22, 18, 20]
3.3.3 获取列表长度
一般使用函数 len() 获取列表长度,具体看看:
age = [23, 18, 19, 20, 22, 18, 20]
print(len(age)) 输出:
7
第四章 操作列表
第三章,我们学习了如何创建列表、以及对列表中元素的简单操作,如果我们要对列表中每个元素进行某个操作,那么就需要遍历列表,具体看看:
4.1 遍历列表
我们可以使用for循环来不断遍历列表中的元素,举例看看:
names = ["xiao hong", "li gang", "da zhuang"]for i in names: # for循环会不断遍历列表中的元素,并赋值给变量iprint(i)输出:
xiao hong
li gang
da zhuang
上述代码中的 i 是我们指定的临时变量,也可以写成其他任意值,一般应该具有一定的指代意义,所以最合适的代码如下:
names = ["xiao hong", "li gang", "da zhuang"]for name in names:print(name)输出:
xiao hong
li gang
da zhuang
4.1.1 在for循环中执行更多操作
我们可以在打印同学名字时,给他们加上一定的信息,如每位同学都是好学生,我们只需要在循环中不断的输出每位同学都是好学校即可!
names = ["xiao hong", "li gang", "da zhuang"] # 列表for name in names: # 循环print(f"{name} is a good student") # 缩进,表示在for的循环体内输出:
xiao hong is a good student
li gang is a good student
da zhuang is a good student
4.1.2 在for循环结束后的操作
我们还可以在for循环结束后,做一些操作
names = ["xiao hong", "li gang", "da zhuang"] # 列表for name in names: # 循环print(f"{name} is a good student") # 缩进,表示在for的循环体内
print("everyone is a good student") # 在循环体外!输出:
xiao hong is a good student
li gang is a good student
da zhuang is a good student
everyone is a good student
4.2 避免缩进错误
python中主要以缩进来划分模块,如上面例子,在for循环语句之后,缩进的表示循环体,没有缩进的表示不是for循环体的!
注意:for循环后面要加冒号(:),表示下面的语句是循环体!
4.3 创建数值列表
上面我们创建了字符串列表,但很多场景下,我们需要一组元素为数字的列表,像班级学生年龄、一年的温度等等,这些都可以用列表来存储!
4.3.1 使用函数 range()
对于连续的一段数,我们可以用 range()函数 来生成,如:
for value in range(1, 3): print(value)输出:
1
2
range()函数 括号内的数是 左闭右开 的,即从括号左边数开始,直到右边界,但不包含右边界!我们再看个例子:
for value in range(3):print(value)输出:
0
1
2
上面的数,从0开始到2,不包括3!
4.3.2 使用range()函数直接创建列表
我们可以将range()函数创建的数直接传入list()函数中,如下:
numbers = list(range(1, 6)) # 将range生成的一系列数直接传入list中,生成列表
print(numbers)输出:
[1, 2, 3, 4, 5]
当然我们也可以先申请一个空列表,再利用for循环不断的添加元素,具体如下:
numbers = [] # 先申请一个空列表for value in range(1, 6): # 循环numbers.append(value) # 添加元素到列表中,append函数上面我们提到过!print(numbers)输出:
[1, 2, 3, 4, 5]
当然我们再添加元素时,也可以对元素进行一些操作:
numbers = [] # 先申请一个空列表for value in range(1, 6): # 循环numbers.append(value ** 2) # 将元素平方,再添加到列表中!print(numbers)输出:
[1, 4, 9, 16, 25]
4.3.3 对数字列表进行简单的统计计算
操作 | 解释 |
---|---|
min() | 返回最小值 |
max() | 返回最大值 |
sum() | 返回列表元素之和 |
举例看看:
numbers = [1, 2, 3, 4, 5] # 列表print(min(numbers)) # 打印最小值
print(max(numbers)) # 打印最大值
print(sum(numbers)) # 打印列表元素之和输出:
1
5
15
4.3.4 列表解析式
上述生成期望列表,一般需要多行代码,采用列表解析式我们可以一行代码搞定,具体为:列表名 = [表达式 循环体 条件] ,具体我们举例看看就懂。
假如我们想要1 - 10之间的偶数:
numbers = [value for value in range(1, 11) if value % 2 == 0]
print(numbers)输出:
[2, 4, 6, 8, 10]
上述代码中:
- value就是表达式,我们也可以对其再进一步操作,如value**2 ,就是再平方
- for value in range(1, 11)就是循环体,不断的迭代输出数
- if value % 2 == 0就是过滤条件,可以不要,即不过滤数据
4.4 列表的切片
上面我们提到了如何用for循环对列表所有元素进行操作,但有时只需要对列表中的部分进行操作,这时就可以用列表的切片操作!
4.4.1 切片
我将通过举例,来解释切片的具体操作:列表名[左索引 :右索引]
注意:
- 和range()函数一样,左闭右开,即右索引对应的元素取不上!
- 索引从0开始,即第一个位置元素的索引是0
下面五个例子包括了所有的切片操作:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表print(numbers[1: 5]) # 取索引1-5的元素
print(numbers[:5]) # 从头开始,一直到索引为5的元素
print(numbers[5:]) # 从索引为5的元素开始,一直到结束
print(numbers[:]) # 从头到尾,即取所有元素!
print(numbers[1:10:2]) # 取索引1-10的元素,步长为2来取数输出:
[2, 3, 4, 5]
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 4, 6, 8, 10]
上面我们还提到过 负号(-) 的使用,表示倒数,如:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表print(numbers[:-2]) # 从头开始,到倒数第2个元素结束输出:
[1, 2, 3, 4, 5, 6, 7, 8]
4.4.2 遍历切片
上面我们对列表所有元素进行了遍历,当然可以对切片的列表进行遍历,我们举例看看:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表for value in numbers[5:]: # 循环遍历切片后的列表print(value) # 不断打印出来输出:
6
7
8
9
10
4.4.3 复制列表
列表的复制有两种方式:
- 我们复制原始列表中的元素,到新列表中
- 我们直接将新的列表名,指向原始的列表名
上述两种方式有什么不同呢?我们举例看看就懂:
- 方式一:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
numbers_copy = numbers[:] # 复制原始列表中的元素到新列表print(numbers)
print(numbers_copy)输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
我们对两个列表再进行操作看看:
numbers.append(100) # 原始列表添加元素100print(numbers)
print(numbers_copy)输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
通过方式一,原始列表添加元素后,新列表不变,说明原始列表和新列表是两个列表,即深拷贝
- 方式二:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 原始列表
numbers_copy = numbers # 指定新列表名,指向原始列表print(numbers)
print(numbers_copy)输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.append(100) # 原始列表添加元素100print(numbers)
print(numbers_copy)输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100]
通过方式二,原始列表添加元素后,新列表也添了元素,说明原始列表和新列表其实是一个列表!,即浅拷贝
4.5 元组
列表适用于在程序运行中,其元素不断发生改变的场景,但有时我们也需要创建一系列值不变的列表,而元素不可变的列表就叫元组
4.5.1 定义元组
元组和列表很像,元组是用 ()圆括号 定义的!我们可以向列表中元素的访问一样,去访问元组中的元素!
我们举例看看就懂:
dimensions = (100, 200) # 元组
print(dimensions[0]) # 打印第一个元素输出:
100
# 元素的值是不能改变!改变的话,就会报错!dimensions = (100, 200) # 元组
dimensions[0] = 300 # 改变第一个元素的值输出:
TypeError: 'tuple' object does not support item assignment
4.5.2 元组的遍历
元组的遍历和列表的遍历一样,我们举例看看:
dimensions = (100, 200) # 元组for value in dimensions: # 循环,遍历print(value) # 打印输出:
100
200
4.5.3 修改元组变量
虽然元组中元素是不能修改的,但是元组变量是可以修改,我们举例看看就懂:
dimensions = (100, 200) # 元组
print(dimensions)dimensions = (300, 400) # 给元组变量重新赋值新的元组
print(dimensions)输出:
(100, 200)
(300, 400)
第五章 if 语句
前面我们学会列表、元组的创建,以及其遍历方式,但有时我们在遍历时,只需要其中一部分数据,如一组数中的偶数;这时,我们就应该不断对列表中元素进行判断!
5.1 一个简单的示例
numbers = [1, 2, 3, 4, 5] # 原始列表for value in numbers: # 循环if value % 2 == 0: # 当除以2余数为0时,即偶数时,打印print(value)输出:
2
4
5.2 条件测试
if 语句的核心就是一个值为 True 或 False 的表达式,当为True时,继续往下走,否则跳出!
5.2.1 检查是否相等
一般用 == 来检查左右两边是否相等!
numbers = [1, 2, 3, 4, 5]for value in numbers:if value == 2: # 等于 2,打印print(value)
5.2.2 检查是否相等时忽略大小写
对于字符串检查相等时,“A” 和 “a”是不一样,如果我们在判断时,想忽略大小写的影响,我们可以用 lower()函数 ,对元素统一变为小写后比较!
names = ["Xiao Hong", "Li Gang", "Da Zhuang"]for name in names:if name.lower() == "li gang": # 若元素统一小写后print(name)输出:
Li Gang
5.2.3 检查是否不相等
一般用 != 来检查左右两边是否不相等!
numbers = [1, 2, 3, 4, 5]for value in numbers:if value != 2:print(value)输出:
1
3
4
5
5.2.4 数值的比较
有一系列的比较数值大小的符号,如: >、<、>=、<=、==,和上面的同理!
5.2.5 检查多个条件
有时我们需要同时满足好几个条件,才能得到我们想要的数据,这时可以用 and 和 or来连接这些条件!
- 使用 and 连接多个条件:
numbers = [1, 2, 3, 4, 5]for value in numbers:if value > 2 and value < 5: # 同时满足这两个条件的, 就打印出来print(value)
输出:
3
4
- 使用 or 连接多个条件:
numbers = [1, 2, 3, 4, 5]for value in numbers:if value < 2 or value > 4: # 满足任意一个条件的,就打印出来print(value)
- 使用圆括号,调整优先级:
numbers = [1, 2, 3, 4, 5]for value in numbers:if (value < 2 or value > 3) and value % 2 == 0: # 满足圆括号内的和括号外的所有条件,就打印print(value)
5.2.6 检查特定值是否在列表中
我们用 in 来检查元素是否在列表中,举例看看:
numbers = [1, 2, 3, 4, 5]print(2 in numbers)输出:
True
5.2.7 检查特定值是否不在列表中
我们用 not in 来检查元素是否不在列表中,举例看看:
numbers = [1, 2, 3, 4, 5]print(8 not in numbers)输出:
True
5.2.8 布尔表达式
布尔表达式和条件测试表达式一样,只是布尔表达式结果要么是True,要么是False。
game_start = True
5.3 if 语句
前面举例中,已经可以看出if语句的写法,其中最简单的为:
5.3.1 简单的if语句
if 条件表达式: # 如果条件测试满足,则执行下面缩进的代码do something
例如:
age = 100
if age > 80: # 满足条件,才执行下面缩进的语句!print("This is a man who lived a long life")输出:
This is a man who lived a long life
5.3.2 if-else语句
对于 if-else 语句,一般在条件满足时,执行 if 语句后面的操作;条件不满足时,执行else后的操作。
if 条件表达式: 某些操作
else:另外一些操作
例如:
age = 50
if age > 80:print("This is a man who lived a long life")else:print("…………………………")输出:
…………………………
5.3.3 if - elif - else结构
我们一般会检查超过两个情形的条件,这时就需要使用 if - elif - else结构 ,python会依次检查每个条件测试语句,测试通过,就会执行其后面的语句,并跳过其他的测试!
age = 12if age < 4: # 年龄 < 4岁, 门票免费print("Your admission cost is 0 yuan")
elif age < 18: # 4 <= 年龄 < 18,门票50元 print("Your admission cost is 50 yuan")
else: # 年龄 >= 18,门票100元print("Your admission cost is 100 yuan")输出:
Your admission cost is 50 yuan
上面的例子中,先检查 if 语句中的表达式是否满足,发现不满足;继续看elif中的语句是否满足,发现满足,就执行其后面的操作(打印);由于elif语句满足了,就不再往下看了,即不会再执行else中的操作。
5.3.4 使用多个elif 代码块
我们可以根据需要,使用多个elif来划分我们的情况,举例如下:
age = 50if age < 4:print("Your admission cost is 0 yuan")
elif age < 15:print("Your admission cost is 20 yuan")
elif age < 40:print("Your admission cost is 50 yuan")
else:print("Your admission cost is 60 yuan")输出:
Your admission cost is 60 yuan
5.3.5 省略else代码块
if-else结构中,else并不是必须存在的,我们也可以将其忽略的,例如:
names = ["Xiao Hong", "Li Gang", "Da Zhuang"]for name in names:if name.lower() == "li gang": # 满足条件,则执行下面操作(打印),对于不满足条件的,我们不做处理!print(name)输出:
Li Gang
5.3.6 测试多个条件
if - elif - else结构,仅仅适用于测试一个条件是否满足,若满足条件,python会跳过剩下的测试。但有时我们需要测试多个条件,这时怎么办呢?
我们可以使用多个 if 语句来做,具体我们举例看看:
information = ["order", "noodles", "rice"]if "order" in information: # 这三个测试条件都会进行检查print("The customer has placed an order")
if "noodles" in information:print("customers eat noodles!")
if "rice" in information:print("customers eat rice!")输出:
The customer has placed an order
customers eat noodles!
customers eat rice!
总结:
- 若只想执行一个代码块,就使用if - elif - else结构
- 若要执行多个代码块,就使用多个if语句
5.4 使用 if 语句处理列表
可以对列表中的元素使用 if 语句,对特定值做动态变化,有助于列表的管理等等!
5.4.1 检查特殊元素
age = [12, 10, 13, 1200, 14] # 初中某班学习年龄的列表数据for value in age: # 循环遍历if 10 < value < 20: # 若在10-20岁之间,正常print("True")else: # 范围之外的,不正常print("False")输出:
True
True
True
False
True
5.4.2 确定列表不是空的
age = [12, 10, 13, 14] # 列表if age: # 若列表存在, 则遍历打印for value in age:print(value)
else: # 若列表不存在,则打印 “数据不存在”print("The data doesn't exist!")输出:
12
10
13
14
5.5 设置 if 语句的格式
在编程习惯,我们一般会在一些地方加空格,来使得代码看起来更加明朗,例如:
if age < 4: #这个要比下面的好!
if age<4:
第六章 字典
和列表不同,python中的字典可以表示的含义更加的广泛!例如我们可以创建一个表示人的字典,并可以在其中存储人的姓名、年龄、职业等等信息!
字典是以键值对存储的,例如 字典名 = {键:值,键:值,等等}
6.1 一个简单的字典
假如我们要存储一个人的姓名和年龄,我们试着用字典来表示:
# 字典 information 中存储了姓名和年龄的信息!
information = {"name": "da zhuang", "age": 18}print(information["name"])
print(information["age"])输出:
da zhuang
18
6.2 使用字典
在python中,字典是一系列 键值对组成 的。每个键都有一个值对应,我们可以使用键来访问对应的值。与键对应的 值可以使数、字符串、列表、字典 都可以!
字典用 {} 来表示,键和值用冒号分隔,键值对之间用逗号隔开!
6.2.1 访问字典中的值
如果想要获取某个键所对应的值,我们可以用: 字典名[键名]
information = {"name": "da zhuang", "age": 18}print(information["name"]) # 获取键name对应的值
print(information["age"]) # 获取键age对应的值输出:
da zhuang
18
6.2.2 添加键值对
字典是动态结构,对于建好的字典,我们可以继续往里面添加键值对,方法为: 字典名[新的键名] = 新的值 , 举例看看就懂:
information = {"name": "da zhuang", "age": 18}
print(information)information['height'] = 165
print(information)输出:
{'name': 'da zhuang', 'age': 18}
{'name': 'da zhuang', 'age': 18, 'height': 165}
6.2.3 先创建一个空字典
很多时候,我们都会先创建一个空的字典,再往里面添加键值对,来达到我们最终要的字典
information = {} # 创建一个空字典
information["name"] = "da zhuang" # 添加键值对
information["age"] = 18 # 添加键值对print(information)输出:
{'name': 'da zhuang', 'age': 18}
6.2.4 修改字典中的值
对于建立好的字典,我们要修改某个键对应的值时,只需要重新赋值即可:字典名[键] = 新值
information = {'name': 'da zhuang', 'age': 18}
information["age"] = 20 # 我们对键age的值,进行修改print(information)输出:
{'name': 'da zhuang', 'age': 20}
6.2.5 删除键值对
对于不要的键值对,我们直接用 del 来删除:del 字典名[键]
information = {'name': 'da zhuang', 'age': 18} # 原始字典
del information["age"] # 删除键值对print(information)输出:
{'name': 'da zhuang'}
删除后的键值对,永远消失,不会再出现的!
6.2.6 使用 get()来访问值
上面我们提到了,可以使用字典中的键来访问其对应的值,若字典中没有这个键,就会报错,我们举例看看:
information = {'name': 'da zhuang', 'age': 18}print(information["color"]) # 字典中没有键color,就会报错!输出:
Traceback (most recent call last):File "C:/Users/Administrator/PycharmProjects/LeetCode/venv/1.py", line 3, in <module>print(information["color"])
KeyError: 'color'
为了防止报错,我们使用 get()函数 来访问键对应的值:值 = 字典 . get(键,默认值) ! 若字典中的键存在,直接返回其对应的值。若没有没有该键,则直接返回默认值!
information = {'name': 'da zhuang', 'age': 18} # 字典age_value = information.get("age") # 键“age”存在,直接返回其值
color_value = information.get("color", "No Value!") # 键“color”不存在,返回默认值(自己定义),不会报错!!!
print(age_value)
print(color_value)输出:
18
No Value!
若我们不知道字典中某个键是否存在,就应该用get()函数!
get(键,默认值):若其中默认值没有定义,并且该键不存在,python会默认返回None!
6.3 遍历字典
字典中存在的键值对可能会很多,我们有时需要对其进行遍历,而字典的遍历方式有多种:键的遍历、值的遍历、键值对的遍历!
6.3.1 遍历键值对:
information = {'name': 'da zhuang', 'age': 18} # 字典for key, value in information.items(): # 遍历键值对print("key: ",key)print("value: ", value)输出:
key: name
value: da zhuang
key: age
value: 18
6.3.2 遍历字典中的键
仅仅访问字典中所以的键: 字典名 . keys()
information = {"1":"aa", "2":"dhe"} # 字典print(information.keys()) # 返回所有的键输出:
dict_keys(['1', '2'])
information = {'name': 'da zhuang', 'age': 18}for key in information.keys():print("key: ",key)输出:
key: name
key: age
6.3.3 按特定顺序遍历字典中的键
可以使用sorted()函数
information = {'name': 'da zhuang', 'age': 18}for key in sorted(information.keys()): # 对键排序(升序)print("key: ",key)输出:
key: age
key: name
information = {'name': 'da zhuang', 'age': 18}for key in sorted(information.keys(), reverse=True): # 对键排序(降序)print("key: ",key)输出:
key: name
key: age
6.3.4 遍历字典中的所有值
仅仅访问字典中的所有值:字典名 . values()
information = {'name': 'da zhuang', 'age': 18}print(information.values())输出:
dict_values(['da zhuang', 18])
information = {'name': 'da zhuang', 'age': 18}for v in information.values():print("value: ", v)输出:
value: da zhuang
value: 18
6.4 嵌套
为了表示更多的信息,有时我们需要将字典存储在列表中、将列表作为值存储到字典中,这种方式就叫做 嵌套 。
6.4.1 字典列表
将字典存储到列表中!
student_1 = {'name': 'da zhuang', 'age': 18} # 学生1的信息
student_2 = {'name': 'li ming', 'age': 19} # 学生2的信息
student_3 = {'name': 'xiao hong', 'age': 18} # 学生3的信息student = [student_1, student_2, student_3] # 将学生的信息放一起
print(student)输出:
[{'name': 'da zhuang', 'age': 18}, {'name': 'li ming', 'age': 19}, {'name': 'xiao hong', 'age': 18}]
6.4.2 在字典中存储列表
可以将列表作为值,存储到字典中
student = {'name': ["da zhuang", 'li ming', 'xiao hong'], 'age': [18, 19, 18]} print(student) # 整体字典
print(student["name"]) # 键name对应的值输出:
{'name': ['da zhuang', 'li ming', 'xiao hong'], 'age': [18, 19, 18]}
['da zhuang', 'li ming', 'xiao hong']
6.4.3 在字典中存储字典
可以将字典作为值,存储到另一个字典中
li_ming = {'name': "da zhuang", 'age': 18} # 字典
xiao_hong = {'name': "da lao", 'age': 20} # 字典Class = {"user1": li_ming, "user2": xiao_hong} # 字典嵌套字典
print(li_ming)
print(xiao_hong)
print(Class)输出:
{'name': 'da zhuang', 'age': 18}
{'name': 'da lao', 'age': 20}
{'user1': {'name': 'da zhuang', 'age': 18}, 'user2': {'name': 'da lao', 'age': 20}}
第七章 用户输入和 while 循环
- 很多时候,我们需要用户自己输入一些信息,来处理具体问题!
- 使用while循环,可以让程序一直执行下去,知道指定的条件不满足为止!
7.1 函数 input()原理
函数input()会暂停程序,等待用户输入,获取用户的输入后,会赋值给指定的变量,然后执行后面的程序!
input_value = input()print("information: ", input_value)输出:
liming # liming 是我们输入的信息
information: liming
通过上面的例子,我们将输入的信息赋值给变量 input_value ,然后打印这个变量!
7.1.1 编写清晰的程序
我们可以在input()函数中加上,用户输入信息的提示符。如:
input_value = input("please enter your name:") # 括号中是提示信息,让用户输入自己名字, input_value 变量为用户输入信息,不会有提示信息的!print("hello! ", input_value)输出:
please enter your name:liming # liming 是我们输入的
hello! liming
7.1 .2 使用input()函数获取数值输入
对于 input()函数 ,python会将用户的 输入 解读为 字符串 , 我们可以用 int()函数 将字符串转换为数值,
age = int(input("please enter your age:")) # int()将字符串15,变为整型15if age >= 18:print("成年人")
else:print("未成年人")输出:
please enter your age:15 # 15是我们输入的
未成年人
7.2 while 循环简介
前面我们提到了for循环,其会遍历集合中的所有元素,而while循环则不断运行,直到指定的条件不满足为止!
7.2.1 使用 while 循环
我们用while循环实现一个简单的数数问题:
count = 1 # 定义变量while count <= 5: # 若count <= 5,就一直执行下面的程序print(count) # 打印count值count += 1 # count 加一输出:
1
2
3
4
5
上面程序,一旦count大于5,不满足循环条件,就不会再执行的!
7.2.2 使用标志
while循环在满足条件时,会一直执行,若需要满足多个条件时,只用一条while检查所有条件会很复杂。
我们可以使用一个变量(标志),来统一所有条件是否都满足,若标志为True,则循环执行,否则跳出!
action = True # 作为标志while action: # 为True,就一直执行print("action something!")
7.2.3 使用 break 退出循环
我们可以使用 break函数 来停止while循环,不论循环条件是否满足!
count = 12while count >= 10: # 满足条件,循环if count < 15: # 满足条件,执行,count自身加一print("action something!")count += 1else: # count 大于等于15,就跳出循环break 输出:
action something!
action something!
action something!
7.2.4 在循环中使用continue
continue仅仅跳出本次循环,在从头开始循环(若条件满足)
7.3 使用 while 循环处理列表和字典
前面提到用for循环来遍历列表中的元素,如果我们想修改列表中的元素时,for循环难以确定元素,我们可以使用while循环来遍历并修改元素!
7.3.1 在列表之间移动元素
student = ["li hong", "xiao ming", "da zhuang"] # 学生姓名
new_class = [] # 新的班级
while student: # 循环(若学生列表有元素)temp_name = student.pop() # 不断弹出new_class.append(temp_name) # 添加到新的班级列表中
print(student)
print(new_class)输出:
[]
['da zhuang', 'xiao ming', 'li hong']
7.3.2 删除列表中特定值
student = ["xiao ming", "li hong", "xiao ming", "da zhuang", "xiao ming"] # 有重复
while "xiao ming" in student: # 若 xiao ming 在学习列表中student.remove("xiao ming") # 删除
print(student)输出:
['li hong', 'da zhuang']
第八章 函数
函数是带名字的代码块,用于完成具体的任务。要执行函数定义的任务,只需要调用该函数就行!
8.1 定义函数
我们以下面的程序为例,关键词def 用来定义函数,其后面紧greet_user是函数名, 圆括号()中执行函数所需的信息,这里不需要额外信息。 greet_user() 是函数的调用,最终直接返回函数结果
def greet_user(): # def 函数名(形参):"""显示问候语""" # 注释,写函数功能等print("hello!!!") greet_user()输出:
hello!!!
8.1.1 向函数传递信息
def 函数名(参数): 函数体
name就是我们想函数中传递的参数!
def greet_user(name): """显示问候语""" print("hello ", name)greet_user("li ming")
8.1.2 实参和形参
上面代码中,变量name是函数中的形参, 即函数完成任务所需的信息;“li ming” 是一个 实参,即调用函数时,传递给函数的信息。
实际执行时,函数greet_user会将实参“li ming”赋值给形参name,然后完成函数!
8.2 传递实参
函数中所需的形参有时很多,我们在调用函数时,需要传递多个实参给函数:
- 位置实参:实参的顺序和形参的顺序一致
- 关键字实参:其中每个实参由变量名和值组成
- 列表以及字典传递
8.2.1 位置实参
我们举例看看:
def student(name, age):print("学生姓名: ", name)print("学生年龄: ", age)student("li ming", 18)输出:
学生姓名: li ming
学生年龄: 18
上面函数有两个形参,所有我们调用函数时,需要传递两个实参,根据位置顺序,实参"li ming"传递给形参name,实参18传递给形参age;位置不能错!!!
函数也可以多次调用!如下面所示:
def student(name, age):print("学生姓名: ", name)print("学生年龄: ", age)student("li ming", 18)
student("da zhuang", 20)输出:
学生姓名: li ming
学生年龄: 18
学生姓名: da zhuang
学生年龄: 20
8.2.2 关键字实参
关键字实参是将参数名和值关联起来,这样可以不受顺序的影响,举例看看就懂:
def student(name, age):print("学生姓名: ", name)print("学生年龄: ", age)student(name = "li ming", age = 18) # 调用时,直接赋值,student(age = 18, name = "li ming") 返回的结果一样!输出:
学生姓名: li ming
学生年龄: 18
8.2.3 默认值
在函数编写时,可以给形参传递默认值,在调用函数时,若给这个形参传递了值,则用该值,若没有赋值,则函数会使用默认值!举例看看:
def student(name, age = 15):print("学生姓名: ", name)print("学生年龄: ", age)student(name = "li ming")输出:
学生姓名: li ming
学生年龄: 15
上述代码:形参age的默认值是15, 函数调用时没有给形参赋值实参,所以按默认值!
def student(name, age = 15):print("学生姓名: ", name)print("学生年龄: ", age)student(name = "li ming", age = 18)输出:
学生姓名: li ming
学生年龄: 18
上述代码:函数调用时,给所以形参都传递了实参,所以不会按照默认值!
8.3 返回值
函数并不是像上面直接显示值,还可以处理数据后,返回一个值或一组值,函数返回的值称为返回值。我们可以用 return语句 将函数处理结果返回出来!
8.3.1 返回简单值
def student(first_name, last_name):name = f"{first_name} {last_name}"return name # 返回函数最终结果(name变量)result_name = student('li', 'ming') # 将函数返回值 name 赋值给 变量 result_name
print(result_name)输出:
li ming
8.3.2 让实参可选
根据上面的代码,有时名字有三个字,我们需要加上一个形参,但名字还有两个字的,所以第三个形参就是可选的,我们可以给它一个默认值!防止报错,并将其放在形参列表的末尾!,放中间会报错!
def student(first_name, last_name, middle_name = ""):if middle_name:name = f"{first_name} {middle_name} {last_name}"else:name = f"{first_name} {last_name}"return nameresult_name = student('li', 'ming')
print(result_name)
result_name = student("xiao", 'ke', 'ai')
print(result_name)输出:
li ming
xiao ai ke
8.3.3 返回字典
函数不仅可以一个值,也可以返回一组值,如列表、字典等等!
def student(first_name, last_name, age = None): # age是可选形参person = {"first": first_name, "last": last_name}if age:person['age'] = agereturn personresult = student('li', 'ming', 17)
print(result)输出:
{'first': 'li', 'last': 'ming', 'age': 17}
8.4 传递列表
有时我们很多信息存储在列表中,这时将信息传递给函数就很方便,我们来看看:
def student(names): for name in names:temp = f"hello {name}"print(temp)usernames = ['li ming', 'xiao hong', 'da zhuang']
student(usernames)输出:
hello li ming
hello xiao hong
hello da zhuang
8.5 传递任意数量的实参
有时,我们不知道函数需要多少个实参,而python可以从调用的函数中取任意数量的实参,具体看看:
def student(*names):print(names)student("li ming") # 传递一个实参和三个实参,可以的
student('li ming', 'xiao hong', 'da zhuang')输出:
('li ming',)
('li ming', 'xiao hong', 'da zhuang')
上述代码中, 形参names前面的 * 会创建一个名为names的空元组,并接受任意传进来的实参封装到元组中。然后传递给函数!
8.5.1 结合位置实参和任意数量实参
注意:
若要让函数接受不同类型的实参,必须在函数定义中将接受任意数量实参的形参放在最后。python先匹配位置参数和关键字参数,再将余下的实参都收集到最后一个形参中!
def student(age, *names):print(age, names)student(18, "li ming") # 将18传给age,剩下的实参传递给names
student(16, 'li ming', 'xiao hong', 'da zhuang') # 将16传给age,剩下的所有实参传递给names输出:
18 ('li ming',)
16 ('li ming', 'xiao hong', 'da zhuang')
8.5.2 使用任意数量的关键字实参
有时,需要接受任意数量的实参,但不知道传递给函数的是什么信息。这时我们可以将函数写为接受任意数量的键值对,调用函数时,传递多少实参就接受多少!举例看看
def student(first, last, **user_info):user_info['first_name'] = firstuser_info['last_name'] = lastreturn user_infouser = student('li', 'ming', age = 18, location = 'princeton')
print(user)输出:
{'age': 18, 'location': 'princeton', 'first_name': 'li', 'last_name': 'ming'}
上述代码中,形参**user_info 中的两个 **会创建一个名为user_info的空字典,并将接收函的所有键值对放入里面!
8.6 将函数存储在模块中
使用函数可以将 代码块 和 主程序 分离开,这样使得主程序显的清晰明了!我们将函数存储在称为模块的独立文件夹中,再将模块导入主程序中。 import 语句可以将模块导入到当前程序中!
8.6.1 导入整个模块
我们首先创建模块。模块的扩展名是 .py文件 ,其中有我们提前写好的一个功能函数。我们举个例子看看:
我们写一个函数如下,文件命名为 print_name.py 。
def print_information(student):print("student information: \n")print(student)
在主程序中,用import语句导入模块(代码),然后
import print_name # print_name 是要导入的文件名student = ['li hong', 'xiao ming', 'da zhuang'] # 定义列表print_name.print_information(student) # 文件名.函数名 就可以调用函数了输出:
student information: ['li hong', 'xiao ming', 'da zhuang']
8.6.2 导入特定的函数
上面我们通过 import语句 导入了整个模块,然后再调用其中具体的函数。我们也可以直接导入我们要使用的具体函数: from 模块文件名 import 函数名
若要导入多个函数可以使用逗号隔开:from 模块文件名 import 函数名,函数名,函数名
所有上面的例子,我们可以直接导入要使用的函数:
from print_name import print_information # 直接导入我们要的函数
student = ['li hong', 'xiao ming', 'da zhuang']print_information(student)输出:
student information: ['li hong', 'xiao ming', 'da zhuang']
8.6.3 使用 as 给函数指定别名
有时导入的函数名和主程序的名称重复,或本身名称过长,这时我们就可以使用as关键词改名!
from print_name import print_information as pi # 使用as改名为pi
student = ['li hong', 'xiao ming', 'da zhuang']pi(student)
8.6.4 使用 as 给模块指定别名
也可以直接对模块改名!
import print_name as pn # 直接改名模块的名称!student = ['li hong', 'xiao ming', 'da zhuang']pn.print_information(student)
8.6.5 导入模块中的所有函数
使用 * 来导入模块中的所有函数!
from print_name import * # 导入模块中的所有函数!student = ['li hong', 'xiao ming', 'da zhuang']print_information(student) # 直接调用就行!
第九章 类
面向对象编程是最有效的软件编写方法之一,在面向对象编程中,我们可以构建一个表现任何事物或情境的类,并根据类创建对象。编写类时,我们所定义的类具有所有对象的通用行为!
基于类创建的对象,都自动具有类的通用行为,然后根据需要赋予每个对象独立的特征,来完成具体任务!
根据类来创建对象称为实例化 , 这样就可以使用类的实例!
9.1 创建和使用类
使用类几乎可以模拟任何东西,我们编写一个小狗的类Dog,这个类不是指特定的小狗,而是任何小狗。 对于小狗来说,它们有名字、年龄,它们还会蹲下、打滚。由于小狗具有上述两个信息(名字、年龄)和两种行为(蹲下、打滚),所有我们的类Dog将包含这些信息!
9.1.1 创建 Dog 类
具体如下:
class Dog: # 定义一个名为Dog的类"""对小狗的简单模拟""" # 对类的功能做说明def __init__(self, name, age): # 初始化方法"""初始化属性name和age"""self.name = name # 定义属性nameself.age = age # 定义属性agedef sit(self): # 定义方法(蹲下)"""模拟小狗收到命令时蹲下!"""print(f"{self.name} is now sitting.")def roll_over(self): # 定义方法(打滚)"""模拟小狗收到命令时打滚"""print(f"{self.name} rolled over")
方法 __ init __() :
- 类中的函数称为方法。前面学到的函数都适用于方法,仅仅是调用方法的方式不同!__ init __() 是一种特殊的方式,每当我们根据Dog类创建新实例时,python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,避免python默认方法和普通方法发生名称冲突。
- 上面我们将方法 __ init __() 定义成包含三个形参:self、name、age,其中形参 self 必不可少,并且需要在 其他形参之前 ! 在python调用这个方法来创建Dog实例时,将 自动传入 实参self 。因此在创建实例时,不需要传递self,只需要给最后两个形参(name、age)提供值!
self.name = name 解释说明:
- 以self为前缀的变量可以供类中的所有方法使用,可以通过类的所有实例来访问。self.name = name 获取和形参name相关联的值,并将其赋值给变量name,然后该变量被关联到当前创建的实例中!像这样可以通过实例访问的变量称为属性
Dog类还定义了另外两个方法,sit() 和 roll_over() ,这些方法执行时不需要额外的信息,因此只有一个形参self。之后创建的实例都能够访问这些方法,即小狗都会下蹲和打滚。当前的两个方法只是打印出来具体的状态,我们也可以对这块复杂化,加一个具体的行动等等!
9.1.2 根据类创建实例
我们创建一个具体的小狗:
# Dog类的创建代码在上面my_dog = Dog("xiao hei", 3)
print(my_dog.name)
print(my_dog.age)输出:
xiao hei
3
my_dog = Dog(“xiao hei”, 3) :
创建了一条名为“xiao hei”、年龄是3的小狗。执行这行代码后,python使用实参“xiao hei”和“3”来调用Dog类的方法 __ init () 。方法 init __()创建一个特定小狗的实例,并将实参传递给形参name和age,之后python返回一个表示这个小狗的实例,而我们将实例赋值给变量 my_dog!
- 访问属性
要访问实例的属性:实例 . 属性名 , 如:my_dog.name - 调用方法
根据类创建实例后,就能使用类中定义的任何方法了:实例 . 方法名 , 具体如下:
my_dog = Dog("xiao hei", 3)
my_dog.sit()
my_dog.roll_over()输出:
xiao hei is now sitting.
xiao hei rolled over
- 创建多个实例
可以按照任务,创建任意数量的实例:
my_dog = Dog("xiao hei", 3) # 创建实例 my_dog
your_dog = Dog("da zhuang", 5) # 创建实例 your_dog print(my_dog.name) # 实例 my_dog 的属性
print(my_dog.age) # 实例 my_dog 的属性
print(your_dog.name) # 实例 your_dog 的属性
print(your_dog.age) # 实例 your_dog 的属性my_dog.sit() # 实例 my_dog的方法
my_dog.roll_over() # 实例 my_dog的方法
your_dog.sit() # 实例 your_dog 的方法
your_dog.roll_over() # 实例 your_dog 的方法输出:
xiao hei
3
da zhuang
5
xiao hei is now sitting.
xiao hei rolled over
da zhuang is now sitting.
da zhuang rolled over
上面,我们定义了两个实例,每个实例都有自己特定的属性,并能够执行相同的方法!
9.2 使用类和实例
可以使用类来描述现实世界的很多事物和情景。类编写好后,我们可以创建很多的实例,我们常常会依据任务来修改实例的属性、方法等等!
9.2.1 Car 类
编写一个表示汽车的类:
class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}" # 汽车整体信息return lone_name.title() # 首字母大写my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name输出:
2019 Aodi A4
上述代码中,我们创建了一个Car类,给了其三个属性(make、model、year)和一个方法(get_descriptive_name),下面我们对它继续修改
9.2.2 给属性指定默认值
创建实例时,有些属性无需通过形参定义,可在方法 __ init __() 中为其指定默认值 。
下面添加一个名为 odometer_reading 的属性,其初始值为0,。我们还添加一个名为read_odometer()的方法,用于读取汽车的里程表:
class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份self.odometer_reading = 0 # 里程数 默认为0def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}"return lone_name.title()def read_odometer(self):"""打印一条汽车公里数的消息"""print(f"This car has {self.odometer_reading} miles on it.")my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_name
my_new_car.read_odometer() # 调用类中的方法 read_odometer输出:
2019 Audi A4
This car has 0 miles on it.
上述代码中,我们给属性 odometer_reading 了一个默认值 0 !即汽车出厂的公里数为0,这一般是不合理的,所以需要对该属性的值进行修改
9.2.3 修改属性的值
一般有三种修改的方法:
- 直接修改属性的值
我们可以通过实例直接对它修改
# Car类 代码和上面相同
my_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_namemy_new_car.odometer_reading = 23 # 直接对属性修改
my_new_car.read_odometer() # 调用方法输出:
2019 Audi A4
This car has 23 miles on it.
- 通过方法修改属性的值
如果可以让某个方法在内部直接对值进行修改,我们就可以不用直接访问属性了
class Car:"""模拟汽车""""""中间同上"""def updata_odometer(self, mileage): # 通过方法直接对属性进行修改!"""将里程数设置为指定值"""self.odometer_reading = mileagemy_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_namemy_new_car.updata_odometer(23) # 调用方法来直接修改属性值
my_new_car.read_odometer() 输出:
2019 Audi A4
This car has 23 miles on it.
- 通过方法对属性的值进行递增
有时我们需要对属性值进行递增,而不是赋予新的值。
class Car:"""模拟汽车""""""中间同上"""def updata_odometer(self, mileage):"""将里程数设置为指定值"""self.odometer_reading = mileagedef increase_odometer(self, miles):"""将里程数增加一定量"""self.odometer_reading += milesmy_new_car = Car("audi", 'a4', '2019') # 创建实例,赋值给 my_new_car
print(my_new_car.get_descriptive_name()) # 调用类中的方法 get_descriptive_namemy_new_car.updata_odometer(2300) # 修改属性(指定里程数)
my_new_car.read_odometer()my_new_car.increase_odometer(100) # 修改属性(增加里程数)
my_new_car.read_odometer()输出:
2019 Audi A4
This car has 2300 miles on it.
This car has 2400 miles on it.
通过上面三种方式:
- 调用实例,直接对属性进行修改
- 通过方法,修改属性
- 通过方法,对属性值进行递增(也可以进行其他操作)
9.3 继承
编写类时,并不是从空白开始,如果我们编写的 类B 是从 类A 改变过来的,可使用继承!类B继承类A时,将自动获得类A的所有属性和方法。这时类A叫做父类,而类B叫做子类。
子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法 !
9.3.1 子类的方法 __ init __()
在现有类的基础上建立新类时,一般要调用父类的方法 __ init __(),这将初始化在父类 __ init __() 方法中定义的所有属性,从而让子类包含这些属性!
上面我们建立了Car类,模拟了汽车,若我们要模拟电动汽车呢?电动汽车具备一般汽车的属性,还有自己的独有属性和方法!
# 定义父类 Car
class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份self.odometer_reading = 0 # 里程数 默认为0def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}"return lone_name.title()def read_odometer(self):"""打印一条汽车公里数的消息"""print(f"This car has {self.odometer_reading} miles on it.")def updata_odometer(self, mileage):"""将里程数设置为指定值"""self.odometer_reading = mileagedef increase_odometer(self, miles):"""将里程数增加一定量"""self.odometer_reading += miles# 定义子类 ElectricCar
class ElectricCar(Car):"""电动汽车"""def __init__(self, make, model, year):"""初始化父类的属性"""super().__init__(make, model, year) # 让子类包含父类的所有属性my_tesla = ElectricCar("tesla", 'model s', '2019') # 创建实例
print(my_tesla.get_descriptive_name()) # 调用父类中的方法输出:
2019 Tesla Model S
- 对于 父类Car 代码,我们在创建子类时,父类必须包含在当前文件中,并且位于子类之前
- 定义子类ElectricCar时,必须在圆括号内指定父类的名称。方法 __ init __() 接受创建Car实例所需的信息!
- super() 是一个特殊函数,让你可以调用父类的方法,上面super()那行代码让python调用Car类的方法__ init __(),让 ElectricCar 实例包含这个方法中定义的所有属性。父类也称为超类,super()就是这么来的!
- 测试继承是否正确,创建实例 my_tesla ,我们给的信息和创建一般车的信息一致(make, model, year),在类ElectricCar中创建实例时,会调用类ElectricCar中的方法__ init __(),然后类中的方法会调用父类Car中定义的方法 __ init __()!
- 对于类ElectricCar,除了方法__ init __()外,没有其他的属性和方法,我们仅仅确定了电动汽车具备一般汽车的属性等!
接下来,我们可以赋予电动车一些自己独特的属性和方法
9.3.2 给子类定义属性和方法
class Car:"""模拟汽车""""""中间同上"""class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year) # 初始化父类的属性self.battery_size = 75 # 初始化电动汽车独有的属性def describe_battery(self):"""打印一条描述电池容量的消息"""print(f"This car has a {self.battery_size} -kwh battery.")my_tesla = ElectricCar("tesla", 'model s', 2019) # 创建实例,赋值给 my_new_car
print(my_tesla.get_descriptive_name()) # 调用类中的方法 get_descriptive_namemy_tesla.describe_battery()输出:
2019 Tesla Model S
This car has a 75 -kwh battery.
上面代码中,根据类ElectricCar创建的所有实例都将包含属性 battery_size , 而父类Car的所有实例都不会包含这个属性。
对子类ElectricCar的特殊程度没有任何限制(可以加入电动车自身独有的任何属性和方法)。但当某个属性或方法是任何汽车都有的,并不是电动车独有的,这时应该将其加入Car类 而不是类ElectricCar中。
9.3.3 重写父类的方法
若父类中的方法不符合子类中的要求,比如Car类中有油箱,但是ElectricCar类中是没有的,这时我们可以定义一个和该方法同名的方法。这样,python就会优先考虑子类中的方法!
例如Car类中有一个名为 fill_gas_tank()的方法,电动车是没有油箱的!因此我们可以重写该方法:
class Car:
"""模拟汽车""""""中间同上"""class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year) self.battery_size = 75def describe_battery(self):"""打印一条描述电池容量的消息"""print(f"This car has a {self.battery_size} -kwh battery.")def fill_gas_tank(self): # 直接对方法fill_gas_tank重写!"""电动车没有油箱"""print("This car doesn't need a gas tank.")
这时,若调用 类ElectricCar中的 fill_gas_tank()方法,python将忽略父类Car中的 fill_gas_tank()方法,而直接调用子类 fill_gas_tank()中的方法!
9.3.4 将实例用作属性
用代码模拟事物时,随着事物的复杂度,我们会添加很多的属性和方法,使得这个文件很长。这种情况下,可能需要将类的一部分提取出来,作为一个新类。
例如描述电动汽车ElectricCar,我们可能会将电池的情况描述的很详细,这时就可以让电池作为新的类Battery,并将一个实例Battery作为类ElectricCar类的属性!具体如下:
class Car:
"""模拟汽车""""""中间同上"""class Battery: """对电池的模拟"""def __init__(self, battery_size = 75):"""初始化电池的大小"""self.battery_size = battery_sizedef describe_battery(self):"""打印一条有关电瓶大小的消息"""print(f"This car has a {self.battery_size} -kwh battery.")class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year) # 初始化父类的属性(Car类)self.battery = Battery() # 初始化电动车的特有属性(battery类)my_tesla = ElectricCar("tesla", 'model s', 2019) # 创建实例(电动汽车的示例)
print(my_tesla.get_descriptive_name()) # 调用父类中的方法
my_tesla.battery.describe_battery() # 实例my_tesla查找属性battery,然后对存储在属性中的Battery实例调用方法describe_battery()
上述代码中:
- 类Battery 定义了电池的一些属性和方法,它没有继承任何类!
- self.battery = Battery() :
- 这里Python会创建一个新的 Battery() 的实例,并将该实例赋值给属性self.battery。
- 类 ElectricCar 中的方法 __ init __ () 每次调用时,都将初始化属性self.battery,即每个ElectricCar实例都包含一个自动创建的Battery实例
9.4 导入类
上面提到,我们可以拆分类来实现整体代码的阅读性,但由于描述的事物过于复杂,整体文件还是会很长,这里我们也可以像函数一样,先将类存储到模块中,再将其导入到主程序中!
9.4.1 导入单个类
我们创建一个 car.py 的文件(模块),来描述汽车!
"""一个用来表示汽车的类""" # 对该文档的说明描述(好的编程习惯,就应该加上具体的描述)class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份self.odometer_reading = 0 # 里程数 默认为0def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}"return lone_name.title()def read_odometer(self):"""打印一条汽车公里数的消息"""print(f"This car has {self.odometer_reading} miles on it.")def updata_odometer(self, mileage):"""将里程数设置为指定值"""self.odometer_reading = mileagedef increase_odometer(self, miles):"""将里程数增加一定量"""self.odometer_reading += miles
然后创建另一个文件 my_car.py,并在其中导入Car类并创建具体实例:
from car import Car # 打开文件(模块)car 导入其中的 Car 类my_new_car = Car("audi", "a8", "2020") # 初始化实例
print(my_new_car.get_descriptive_name()) # 调用方法my_new_car.odometer_reading = 52 # 属性赋值
my_new_car.read_odometer() # 调用方法输出:
2020 Audi A8
This car has 52 miles on it.
9.4.2 在一个模块中存储多个类
同一个模块中的类有一定的相关性,但也可以根据需要在一个模块中存储任意数量的类。我们在上面Car类的基础上再加 Battery类和ElectricCar类 !
"""一组用于表示燃油车和电瓶汽车的类""" # 对文件(模块)的描述class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份self.odometer_reading = 0 # 里程数 默认为0def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}"return lone_name.title()def read_odometer(self):"""打印一条汽车公里数的消息"""print(f"This car has {self.odometer_reading} miles on it.")def updata_odometer(self, mileage):"""将里程数设置为指定值"""self.odometer_reading = mileagedef increase_odometer(self, miles):"""将里程数增加一定量"""self.odometer_reading += milesclass Battery:"""对电池的模拟"""def __init__(self, battery_size = 75):"""初始化电池的大小"""self.battery_size = battery_sizedef describe_battery(self):"""打印一条有关电瓶大小的消息"""print(f"This car has a {self.battery_size} -kwh battery.")def get_range(self):"""打印一条描述电瓶容量的消息"""if self.battery_size == 75:range = 260elif self.battery_size == 100:range = 315print(f"This car can go about {range} miles on a full charge.")class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year) # 初始化父类的属性self.battery = Battery() # 初始化电动车的特有属性
现在创建一个名为 my_electric_car.py 的文件,将上面的导入:
from car import ElectricCar # 打开文件(模块)导入 类ElectricCar my_tesla = ElectricCar("tesla", "model s", 2020) # 创建实例
print(my_tesla.get_descriptive_name()) # 调用方法my_tesla.battery.describe_battery() # 调用方法
my_tesla.battery.get_range() # 调用方法输出:
2020 Tesla Model S
This car has a 75 -kwh battery.
This car can go about 260 miles on a full charge.
9.4.3 从一个模块中导入多个类
可以在主程序中导入任意数量的类,比如我们要创建一个普通汽车和电动汽车,那么我们就要导入Car类和ElectricCar类:
from car import Car, ElectricCar # 从文件(模块)导入类Car、类ElectricCarmy_beetle = Car("volkswagen", "beetle", 2020) # 创建实例
print(my_beetle.get_descriptive_name()) # 调用方法my_tesla = ElectricCar("tesla", "model s", 2020) # 创建实例
print(my_tesla.get_descriptive_name()) # 调用方法输出:
2020 Volkswagen Beetle
2020 Tesla Model S
9.4.4 导入整个模块
上面我们导入模块中的一个类、多个类,当然也可以导入整体模块,然后根据句点法调用具体的类!
import car # 导入整个模块my_beetle = car.Car("volkswagen", "beetle", 2020) # 创建实例(调用具体类)
print(my_beetle.get_descriptive_name())my_tesla = car.ElectricCar("tesla", "model s", 2020) # 创建实例(调用具体类)
print(my_tesla.get_descriptive_name())输出:
2020 Volkswagen Beetle
2020 Tesla Model S
9.4.5 导入模块中的所有类
要导入模块(文件)中的所有类,可以用:
from model_name import * # 这样导入了模块(文件)中的所有类
这种做法的有一些缺点:
- 我们不知道具体导入的类名称
- 导入的类名 可能会和主程序中某些命名冲突,不易发现
我们可以用9.4.4中的做法,导入模块后,用句点法来使用具体的类!
9.4.6 在一个模块中导入另一个模块
有时,我们会把类存储在多个模块中,以免模块太多!将类存储在多个模块中,有时一个模块中的类可能会依赖其他模块中的类,这时可在前一个模块中导入必要的类!举例说明:
我们将Car类存储在一个模块car.py中,ElectricCar类、Battery类存储在另一个模块electric_car.py中:
模块 car.py:
"""用于表示汽车的类""" # 对文件(模块)的描述class Car:"""模拟汽车"""def __init__(self, make, model, year):"""初始化描述汽车的属性"""self.make = make # 制造商self.model = model # 型号self.year = year # 生产年份self.odometer_reading = 0 # 里程数 默认为0def get_descriptive_name(self):"""返回清晰的信息"""lone_name = f"{self.year} {self.make} {self.model}"return lone_name.title()def read_odometer(self):"""打印一条汽车公里数的消息"""print(f"This car has {self.odometer_reading} miles on it.")def updata_odometer(self, mileage):"""将里程数设置为指定值"""self.odometer_reading = mileagedef increase_odometer(self, miles):"""将里程数增加一定量"""self.odometer_reading += miles
模块 electric_car.py:
- 由于ElectricCar类用到了类Car,所有应先将类Car导入
"""用于表示电动汽车和电池的类""" # 对文件(模块)的描述from car import Car # 先将类Car 导入class Battery:"""对电池的模拟"""def __init__(self, battery_size = 75):"""初始化电池的大小"""self.battery_size = battery_sizedef describe_battery(self):"""打印一条有关电瓶大小的消息"""print(f"This car has a {self.battery_size} -kwh battery.")def get_range(self):"""打印一条描述电瓶容量的消息"""if self.battery_size == 75:range = 260elif self.battery_size == 100:range = 315print(f"This car can go about {range} miles on a full charge.")class ElectricCar(Car):"""电动汽车的独特之处"""def __init__(self, make, model, year):super().__init__(make, model, year) # 初始化父类的属性self.battery = Battery() # 初始化电动车的特有属性
主程序 my_cars.py:
from car import Car
from electric_car import ElectricCarmy_beetle = Car("volkswagen", "beetle", 2020)
print(my_beetle.get_descriptive_name())my_tesla = ElectricCar("tesla", "model s", 2020)
print(my_tesla.get_descriptive_name())输出:
2020 Volkswagen Beetle
2020 Tesla Model S
9.4.7 使用别名
上一章中,函数导入时可以将函数名改为其他名称,对于类也是可以的!举例如下:
from electric_car import ElectricCar as EC # 将类ElectricCar 改为 EC
若要创建电动车实例时,只需要调用 EC就行
my_tesla = EC("tesla", "model s", 2020)
9.5 python 标准库
python标准库是一组模块,我们安装好python后就包含它了。我们对函数和类的模块原理已经了解了,同理也使用其他人编写好的模块,我们只需要: import 模块名
以 random模块 为例,它其中有一个函数为 randint()
from random import randint # 导入模块result = randint(1, 10) # 传入两个整数,返回其范围中任意数字
print(result)输出:
4
模块random中,另外一个函数choice()。它将一个列表或元组作为参数,返回其中随机一个元素:
from random import choiceresult = choice(["li ming", "xiao hong", "da zhuang"])
print(result)输出:
xiao hong
第十章 文件和异常
本章学习python对文件的处理、对程序运行错误的处理以及json模块,用来保存数据防止程序停止运行后丢失!
10.1 从文件中读取数据
日常中,文本文件最多,我们应该学会如何去处理这些文件,在使用或处理这文本时,我们应先读取这些文件,可以一次性全部读取,也可以逐行的读取!
10.1.1 读取整个文件
首先我们创建一个文本文件 pi_digits.txt ,其内容为:
3.1415926535
8979323846
2643383279
我们一次性读取文本中所有内容
with open("pi_digits.txt") as file_object: # 打开文件contents = file_object.read() # 读取文件所有内容print(contents)输出:
3.1415926535
8979323846
2643383279
我们解读一下上面的代码:
- open(文件目录):会打来要读取的文件,并返回该文件的一个对象
- as 变量名:会将上面的对象赋值给变量 file_object
- with:可以让python自动的判断什么时候打开文件,什么时候关闭文件
- 有个文件的对象之后,就可以用 read()函数 读取文件的全部内容
10.1.2 文件路径
上面代码中,open()函数中传递的文件目录是相对路径,即该文件所在目录相对于当前程序运行所在的目录!有时为了防止出错,可以使用绝对路径,即文件在计算机中的位置!
10.1.3 逐行读取
有时我们需要对文件中的内容进行逐行的读取,用于修改或查看等等!我们继续用上面的例子来说;
filename = "pi_digits.txt" # 文件的路径with open(filename) as file_object: # 打开文件for line in file_object: # 逐行读取(通过循环)print(line) # 打印输出:
3.141592653589793238462643383279
上述打印出来的有很多的空行,和文件中的不一样,因为文件中每行的末尾都有一个换行符,而print()在读取时也会加上一个换行符,这时就有两个换行符:一个来自文件,一个来自print()函数,我们可以使用rstrip()函数来消除:
filename = "pi_digits.txt"with open(filename) as file_object:for line in file_object:print(line.rstrip())输出:
3.1415926535
8979323846
2643383279
10.1.4 创建一个包含文件各行内容的列表
使用关键词with时,open()返回的文件对象只能在with代码块中使用。若要在with代码块外面访问文件内容,可以在with代码块中将文件各行存储在一个列表中,然后在with代码块外面使用!
filename = "pi_digits.txt" # 文件目录with open(filename) as file_object: # 打开文件lines = file_object.readlines() # 读取文件,存放到列表中print(lines)for line in lines: # 通过循环打印出文件信息print(line.rstrip())输出:
['3.1415926535\n', '8979323846\n', '2643383279'] # 整个文件存储在列表中,每行作为列值中一个元素
3.1415926535
8979323846
2643383279
10.2 写入文件
当我们想要保存某些数据时,通常的做法就是直接对其保存,将数据写到一个文件中!举例看看:
10.2.1 写入空文件
filename = "programming.txt" # 文件目录with open(filename, "w") as file_object: # 打开文件,写入模式file_object.write("I love programming") # 写入数据(此处是一个字符串)
# programming.txt 文件中的内容
I love programming
解释上述代码:
- open(文件目录, “w”):函数 open() 中包含两个参数:一个文件目录,一个是写入模式(告诉python要往文件中写入数据);当然还有其他的模式,例如读取模式(“r”)、附加模式(“”)、读写模式(“r+”)
- 若在写入时不存在文件 programming.txt,python会自动创建一个名为programming.txt的文件,并往里面写入数据
- 若在写入时存在文件programming.txt,python会自动删除文件中的内容,再往里面写入数据!
10.2.2 写入多行文件
函数 write()不会在写入的文件末尾添加换行符,若要写入多行文件时,可能达不到预期想要的!举例看看:
filename = "programming.txt"with open(filename, "w") as file_object:file_object.write("I love programming.")file_object.write("I love creating new games.")
查看文件,发现上面写入的两句话变成一行了!
# programming.txt 文件中的内容
I love programming.I love creating new games.
要让每个字符串占一行,就应该在字符串后面加换行符!
filename = "programming.txt"with open(filename, "w") as file_object:file_object.write("I love programming.\n") # 字符串后面加换行符file_object.write("I love creating new games.\n")
# programming.txt 文件中的内容
I love programming.
I love creating new games.
10.2.3 附加到文件
上面提到,在 写入模式(“w”) 中,若文件已经存在,python会将文件中的内容删除,再写入数据。那若要在原有文件继续写入数据呢?这时就要使用附加模式(“s”),当然文件若不存在,python也是会提前创建一个空文件的!
我们对上面的文件 programming.txt 继续修改,给它添加一些信息:
filename = "programming.txt"with open(filename, "a") as file_object:file_object.write("I also love finding meaning in large datasets.\n")file_object.write("I love creating apps that can run in a browser.")
# programming.txt 文件中的内容
I love programming.
I love creating new games.
I also love finding meaning in large datasets.
I love creating apps that can run in a browser.
我们发现,原本的文件信息还在,下面两行是刚添加上的!
10.3 异常
程序发生错误后,会停止运行并报错;但是有时我们不知道程序还有什么问题,为了提前避免程序发生错误停止运行,python中有称为异常的一个对象可以管理程序发生错误!当程序发生错误后,会走我们提前指定的路线执行!
异常吹模块: try - except
10.3.1 处理 ZeroDivisionError 异常
我们知道除法中,除数不能为零,程序碰到这种情况会报错,我们看看:
print(5/0)输出:
Traceback (most recent call last):File "C:/Users/Administrator/PycharmProjects/venv/my_cars.py", line 1, in <module>print(5/0)
ZeroDivisionError: division by zero
python一旦遇到错误就会停止执行!
10.3.2 使用 try - except 模块
一般就代码块放在try语句下,若代码块报错,将执行except下的代码,若代码块没有报错,就忽略except下的代码!
try:print(5/0) # 代码在try中,报错则执行except;否则忽略except
except ZeroDivisionError: print("You can't divide by zero")
由于知道try中程序可能报ZeroDivisionError错误,若不知道将会报什么错,也可以不写,如下:
try:print(5/0)
except: # 直接写except print("You can't divide by zero")
10.3.3 使用异常避免崩溃
有时程序在执行过程中,为了防止报错而导致后续程无法执行,就应该加上try-except:
print("这是一个简单的除法计算器")while True:first_number = input("请输入第一个数: ")second_number = input("请输入第二个数: ")answer = float(first_number) / float(second_number)print(answer)输出:这是一个简单的除法计算器
请输入第一个数: 5
请输入第二个数: 0
Traceback (most recent call last):File "F:/py_object/alien_invasion/1.py", line 6, in <module>answer = float(first_number) / float(second_number)
ZeroDivisionError: float division by zero
上述代码中,当除数为零时就会报错,导致程序后续无法执行,这时就应该用异常处理模块!
10.3.4 else 代码块
在python中,若将代码块放在try中,若程序报错,就执行except中的代码,若执行成功,我们可以在else中进行打印或执行:
print("这是一个简单的除法计算器")while True:first_number = input("请输入第一个数: ")second_number = input("请输入第二个数: ")try:answer = float(first_number) / float(second_number)except ZeroDivisionError:print("除数不应该为零")else:print(answer)输出:这是一个简单的除法计算器
请输入第一个数: 5
请输入第二个数: 0
除数不应该为零
10.3.5 处理 FileNotFoundError 异常
处理文件数据时,若程序找不到文件一般会报错,
filename = "ceshi.txt"try:with open(filename, encoding='UTF-8') as file: # 打开文件lines = file.read()
except FileNotFoundError: # 报错print(f"Sorry, The file {filename} does not exist")输出:
Sorry, The file ceshi.txt does not exist
我们还会遇到很多的错误,基本都可以使用这样的方式去处理!
10.3.6 静默失败
前面程序中,程序遇到错误后,都会去执行excep中的程序,我们都会打印一个报错的信息,但有时我们想一直去执行,不需要打印什么报错信息,这时就可以使用 pass
filename = "ceshi.txt"try:with open(filename, encoding='UTF-8') as file: # 打开文件lines = file.read()
except FileNotFoundError: # 若出错,什么都不打印!pass 输出:
10.4 存储数据
我们经常需要把程序中的一些数据如:列表、字典等数据保存在文件中!一种简单的方式是使用 json模块 存储数据!
JSON数据格式并非python专用,可以和其他编程语言一起共享数据!
10.4.1 使用 json.dump() 和 json.load()
我们举例看看:
# 写文件
import json # 导入json模块numbers = [1, 2, 3, 4, 5] # 要存储的列表
filename = "numbers.json" # 文件
with open(filename, 'w') as file: # 打开文件json.dump(numbers, file) # 写入列表到文件中
# 读取文件
import jsonfilename = "numbers.json" # 文件
with open(filename, 'r') as file: # 打开文件numbers = json.load(file) # 加载文件print(numbers)输出:
[1, 2, 3, 4, 5]
第 11 章 测试代码
我们写好的代码,都应该经过一系列的测试去看是否达到我们的预期!
11.1 测试函数
我们先写一个简单的代码:
# 传入姓和名,打印出完整的姓名,首字母大写
def get_formatted_name(first, last):"""生成完整的姓名"""full_name = f"{first} {last}"return full_name.title()
我们重新建立一个python脚本,将上面函数导入。并编写测试函数:
from name_function import get_formatted_name # 导入函数print("Enter 'q' at any time to quit.\n") while True:first = input("Please give me a first name: ")if first == "q":breaklast = input("Please give me a last name: ")if last == "q":breakformatted_name = get_formatted_name(first, last)print(f"Neatly formatted name: {formatted_name}")
11.1.1 单元测试和测试用例
python中的 模块unittext 提供了代码测试工具。
单元测试:核实函数的某些方面没有问题
测试用例:是一组测试单元,用来核实函数在各种情形下的行为都符合要求!
11.1.2 可通过的测试
我们使用python中的unittest模块!
import unittest # python标准库
from name_function import get_formatted_name # 被测试的函数class NameTestCase(unittest.TestCase): # 要继承unittest.TestCase这个类def test_first_last_name(self):"""测试像姓和名为 'janis' 和 'joplin' 的用例"""formatted_name = get_formatted_name('janis', 'joplin')self.assertEqual(formatted_name, 'Janis Joplin') # assertEqual:断言方法,用来核实输出和期望是否一致if __name__ == '__main__':unittest.main()输出:
============================= test session starts =============================
platform win32 -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- D:\Anaconda\python.exe
cachedir: .pytest_cache
rootdir: F:\py_object\alien_invasion
plugins: arraydiff-0.3, doctestplus-0.4.0, openfiles-0.4.0, remotedata-0.3.2
collecting ... collected 1 itemtest_name_function.py::NameTestCase::test_first_last_name PASSED [100%]============================== 1 passed in 0.02s ==============================
《python编程:从入门到实战》学习笔记相关推荐
- 第二行代码学习笔记——第六章:数据储存全方案——详解持久化技术
本章要点 任何一个应用程序,总是不停的和数据打交道. 瞬时数据:指储存在内存当中,有可能因为程序关闭或其他原因导致内存被回收而丢失的数据. 数据持久化技术,为了解决关键性数据的丢失. 6.1 持久化技 ...
- 第一行代码学习笔记第二章——探究活动
知识点目录 2.1 活动是什么 2.2 活动的基本用法 2.2.1 手动创建活动 2.2.2 创建和加载布局 2.2.3 在AndroidManifest文件中注册 2.2.4 在活动中使用Toast ...
- 第一行代码学习笔记第八章——运用手机多媒体
知识点目录 8.1 将程序运行到手机上 8.2 使用通知 * 8.2.1 通知的基本使用 * 8.2.2 通知的进阶技巧 * 8.2.3 通知的高级功能 8.3 调用摄像头和相册 * 8.3.1 调用 ...
- 第一行代码学习笔记第六章——详解持久化技术
知识点目录 6.1 持久化技术简介 6.2 文件存储 * 6.2.1 将数据存储到文件中 * 6.2.2 从文件中读取数据 6.3 SharedPreferences存储 * 6.3.1 将数据存储到 ...
- 第一行代码学习笔记第三章——UI开发的点点滴滴
知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...
- 第一行代码学习笔记第十章——探究服务
知识点目录 10.1 服务是什么 10.2 Android多线程编程 * 10.2.1 线程的基本用法 * 10.2.2 在子线程中更新UI * 10.2.3 解析异步消息处理机制 * 10.2.4 ...
- 第一行代码学习笔记第七章——探究内容提供器
知识点目录 7.1 内容提供器简介 7.2 运行权限 * 7.2.1 Android权限机制详解 * 7.2.2 在程序运行时申请权限 7.3 访问其他程序中的数据 * 7.3.1 ContentRe ...
- 第一行代码学习笔记第五章——详解广播机制
知识点目录 5.1 广播机制 5.2 接收系统广播 * 5.2.1 动态注册监听网络变化 * 5.2.2 静态注册实现开机广播 5.3 发送自定义广播 * 5.3.1 发送标准广播 * 5.3.2 发 ...
- 第一行代码学习笔记第九章——使用网络技术
知识点目录 9.1 WebView的用法 9.2 使用HTTP协议访问网络 * 9.2.1 使用HttpURLConnection * 9.2.2 使用OkHttp 9.3 解析XML格式数据 * 9 ...
- 安卓教程----第一行代码学习笔记
安卓概述 系统架构 Linux内核层,还包括各种底层驱动,如相机驱动.电源驱动等 系统运行库层,包含一些c/c++的库,如浏览器内核webkit.SQLlite.3D绘图openGL.用于java运行 ...
最新文章
- 算法--------旋转数组
- ubuntu文件权限解析
- C#使用NPOI导出Excel文件
- 微软Connect(); 2017大会梳理:Azure、数据、AI开发工具
- C++ 标准输入流01
- 注意力机制-深度学习中的注意力机制+注意力机制在自然语言处理中的应用
- java中nonce_java如何获取微信timestamp,nonceStr,signature参数
- 按钮点击打开新页面_PDF怎么打开?如何制作一个PDF格式的文档?
- Linux简单实用小技巧
- Python工程师必看的面试问题与解答(中) 1
- python爬虫实践
- 怎么调html分辨率,屏幕分辨率怎么调
- 英汉词典 JaVa_一个Java编写的英汉词典
- 天下3为啥不显示服务器列表,69级封顶,孩子、画卷系统关闭……《天下3》全新主题服务器玩法全公开!...
- 大数据精准营销数据分析处理(一)
- 美通企业日报 | 拜耳健康消费品中国研发中心开幕;TCL上半年电视机销量稳居全球第二...
- 各种生物识别的优缺点
- 算法笔记 刷题2.6
- BZOJ1023 [SHOI2008]仙人掌图
- Linux 网桥配置br-lan、eth0、eth1、ra0、rai0
热门文章
- (转)人工智能步入金融领域的主流玩法
- OpenAnolis社区致Linux开发者的一封信
- 【基础处理】基于matlab Fxlms算法有源噪声控制系统【含Matlab源码 1394期】
- 【图像几何】基于matlab GUI图像拉东变换【含Matlab源码 848期】
- 树莓派开发界面显示温度_关于树莓派linux开发板
- cpu内存和线程和pool多进程池 Python
- 用DFS深度优先搜索求 1~n 的全排列
- js 多个定时器_《进击的前端工程师》Node.js事件循环
- table()函数--R语言
- 「干货」模拟信号和数字信号的差异