[TOC] #### 1. Debug 工具 --- Debug 工具是 PyCharm IDE 中集成的用来调试程序的工具,在这里程序员可以看到程序的执行细节和流程或者调试 bug Debug 工具使用步骤:打断点、Debug 调试 打断点: + 断点位置:目标要调试的代码块的第一行代码即可,即一个断点即可。 + 打断点的方法:单击目标代码的行号右侧空白位置 Debug 调试:右键单击文件内容空白处,点击菜单中的 “调试 xx”。可使用以下代码片段测试 “调试工具”: ```python name = 'liang' print(name) schoolName = '人生苦短,我用 Python' print(schoolName) ``` #### 2. 数据类型及转换 --- 认识 Python 中的数据类型 ```python # int 整型 print(type(1)) # float 浮点型 print(type(3.14)) # str 字符串,特点:数据都要带引号 print(type("hello")) # bool 布尔型,通常判断使用,有两个取值 True、False(注意大小写,首字母大写) print(type(True)) print(type(False)) # list 列表 c = [10, True, 'hello'] print(type(c)) # tuple 元组 d = (10, 3.14, 'liang') print(type(d)) # set 集合 e = {10, 20, 'wuxi'} print(type(e)) # dict 字典 f = { 'name': 'liang', 'age': 18 } print(type(f)) ``` 数据类型之间的转换 ```python # 将数据转为浮点型 num = 1 str = '3.14' print(float(num)) print(float(str)) # 将列表转为元组 list1 = [10, True, 'liang'] print(tuple(list1)) # 将元组转为列表 t1 = (10, 20, 30) print(list(t1)) # eval() 计算在字符串中的有效 Python 表达式,并返回一个对象 str1 = '1' str2 = '1.1' str3 = '(10, True, "liang")' print(type(eval(str1))) print(type(eval(str2))) print(type(eval(str3))) ``` #### 3. if 条件语句 --- 条件语句:即条件成立执行某些代码,条件不成立则不执行这些代码或执行其它代码片段 ```python if True: print('条件成立执行的代码1') print('条件成立执行的代码2') if False: print('条件成立执行的代码3') print('条件成立执行的代码4') # 注意:下方没有加缩进的代码不属于 if 语句块,即和条件是否成立无关 print('这个代码会执行吗?') ``` 简单条件语句:`if ... else` ```python # 需求:年龄大于等于18,输出已经成年,可以去网吧上网 # 获取到的输入内容是字符串,需要转为数字类型 age = int(input('请输入您的年龄:')) # if else 简单条件语句 if age >= 18: print(f'您输入的年龄: {age},已经成年,可以去网吧上网') else: print(f'抱歉,您输入的年龄: {age},未成年,不可以去网吧') ``` 多重判断条件语句:`if ... elif ... else` ```python age = int(input('请输入您的年龄:')) if age < 18: print(f'您输入的年龄: {age},童工') elif age <= 60: print(f'抱歉,您输入的年龄: {age},合法工龄') else: print(f'抱歉,您输入的年龄: {age},法定退休年龄') ``` if 语句的嵌套 ```python age = int(input('请输入您的钱包余额:')) seat = True # 是否有座位 if age >= 2: print(f'您的余额足够坐公交车') if seat: print('车上还有座位') else: print('每座了,只好站着了') else: print(f'抱歉,余额不足,不能坐公交车了') ``` 猜拳游戏案例: ```python # 导入 random 模块,使用这个模块中的功能 random.randint() 生成随机整数 import random # 玩家出拳 player = int(input("请出拳:0-石头 1-剪刀 2-布 --> ")) # 电脑出拳 computer = random.randint(0, 2) print(f"玩家出拳: {player}") print(f"电脑出拳: {computer}") if (player == 0 and computer == 1) or (player == 1 and computer == 2) or (player == 2 and computer == 0): print('恭喜,玩家获胜') elif player == computer: print('平局,还没分出胜负,再来一局吧') else: print('抱歉,电脑获胜') ``` #### 4. 运算符 --- 三目运算符也叫三元运算符或三元表达式,语法如下: ```plaintext 条件成立执行的表达式 if 条件 else 条件不成立执行的表达式 ``` 使用示例 ```python a = 1 b = 2 c = a if a > b else b # a > b 条件成立,返回 a 不成立返回 b print(c) # 2 d = 10 e = 8 f = d if d > e else e print(f) # 10 ``` 运算符的分类: + 算术运算符 + 赋值运算符 + 复合赋值运算符 + 比较运算符 + 逻辑运算符 前三类运算符(算术/赋值/复合赋值运算符)已在 [Python 零基础教程【入门篇】](https://www.itqaq.com/index/714.html) 中学习过,所以本文从比较运算符学习 赋值运算符作一个补充: ```python # 单个变量赋值 a = 1 b = 2 # 多个变量赋值(左边的变量名数量和右侧的数据数量必须一致) num1, num2, str = 10, 20, 'liang' print(num1, num2, str) # 多变量赋相同的值 c = d = 100 print(c, d) ``` 比较运算符 | 运算符 | 描述 | | ------------ | ------------ | | == | 判断相等。如果两个操作数的结果相等,则条件结果为真(True),否则条件结果为假(False) | | != | 不等于。如果两个操作数的结果不相等,则条件结果为真(True),否则条件结果为假(False) | | > | 判断运算符左侧操作数结果是否大于右侧操作数结果,如果大于,则条件为真,否则为假 | | < | 判断运算符左侧操作数结果是否小于右侧操作数结果,如果小于,则条件为真,否则为假 | | >= | 判断运算符左侧操作数结果是否大于等于右侧操作数结果,如果小于,则条件为真,否则为假 | | <= | 判断运算符左侧操作数结果是否小于等于右侧操作数结果,如果小于,则条件为真,否则为假 | 逻辑运算符 | 运算符 | 逻辑表达式 | 描述 | | ------------ | ------------ | ------------ | | and | x and y | 布尔 “与”,如果 x 为 False,x and y 返回 False,否则它返回 y 的值 | | or | x or y | 布尔 “或”,如果 x 为 True,x or y 返回 True,否则它返回 y 的值 | | not | not x | 布尔 “非”,如果 x 为 True,返回 False;如果 x 为 False,返回 True | ```python a = 2 b = 4 c = 6 # and 都真才真,一假就假 print(a < b and c > b) # True print(a > b and c > b) # False # or 一真就真,都假才假 print(a < b or c > b) # True print(a > b or c > b) # True # not 非:取反 print(not False) # True print(not a > b) # True ``` #### 5. 循环语句 --- 循环的作用:让代码更高效的重复执行,不需要重复写多次相同的代码段 循环的分类:在 Python 中,循环分为 `while` 和 `for` 两种,最终实现效果相同 快速体验 `while` 循环 ```python # 需求: 重复执行 5 次 print("媳妇儿,我错了") i = 0 while i < 5: print(f"{i}-媳妇儿,我错了") i += 1 ``` `while` 循环的应用 ```python # 需求: 计算1-100中的偶数累加和 # 方法一: 条件判断和取余数 i = 1 sum = 0 while i <= 100: if i % 2 == 0: sum += i i += 1 print(f"1-100的累加和:{sum}") # 2550 # 方法二: 计数器控制 j = 2 sum2 = 0 while j <= 100: sum2 += j j += 2 print(f"1-100的累加和:{sum2}") # 2550 ``` `break` 和 `continue` 是循环中满足一定条件退出循环的两种不同方式 + break:终止此循环 + continue:退出当前一次循环,继续执行下一次循环代码 ```python # break 终止循环,后续也不再进行循环 i = 1 while i <= 5: if i == 3: print(f"第{i}个苹果吃完了,吃饱了") break else: print(f"第{i}个苹果吃完了,还没吃饱") i += 1 # continue 结束本次循环,继续下一次的循环 i = 1 while i <= 5: if i == 3: print(f"第{i}个苹果有虫子,我不吃这个") i += 1 continue print(f"第{i}个苹果吃完了") i += 1 ``` `while` 循环语句的嵌套 ```plaintext while 条件1: 条件1成立执行的代码 ...... while 条件2: 条件2成立执行的代码 ... ``` 打印星星,每行输出的星星数量逐行递增 ```python # 循环 n 次,每次输出的 * 数量逐行递增 i = 0 while i < 5: j = 0 while j <= i: print('*', end='') j += 1 print() i += 1 ``` 循环嵌套经典练习题:九九乘法表 ```python # 需求:打印九九乘法表 i = 1 while i <= 9: j = 1 while j <= i: print(f'{j}x{i}=' + str(i * j), end="\t") j += 1 i += 1 print() ``` `for` 循环语法格式: ```plaintext for 临时变量 in 序列: 重复执行的代码1 重复执行的代码2 ``` 快速体验: ```python str = 'liang123' for item in str: if item == 'a': print('遇到a不打印') continue # 结束本次循环 if item == 'g': print('遇到g终止循环') break # 终止本次循环 print(item) ``` 需求:女朋友生气了,要惩罚连续说 5 遍 “媳妇儿,我错了”。如果道歉正常完毕女朋友就原谅我了,这个程序应该怎么写 ? + 思考:这个 print 是不是没有循环也能执行 ? ```python i = 1 while i <= 5: print('媳妇儿,我错了') i += 1 print('媳妇儿原谅我了') ``` `while ... else` 语法: ```plaintext while 条件: 条件成立重复执行的代码 else: 循环正常结束之后要执行的代码 ``` 使用示例 ```python i = 1 while i <= 5: print('媳妇儿,我错了') i += 1 else: print('媳妇儿原谅我了') ``` 退出循环的方式 所谓 `else` 指的是正常结束之后要执行的代码,即:如果是 `break` 终止循环的情况,`else` 下方缩进的代码将不执行 ```python i = 1 while i <= 5: if i == 3: print('这遍说的不真诚') break # 终止循环,那么 else 中的代码将不会执行 print('媳妇儿,我错了') i += 1 else: print('真开心,媳妇儿原谅我了') # 这段代码不会执行 ``` `continue` 不会影响 `else` 下方缩进代码的执行 ```python i = 1 while i <= 5: if i == 3: i += 1 continue # 结束本次循环,else 中的代码还会执行 print('媳妇儿,我错了') i += 1 else: print('真开心,媳妇儿原谅我了') # 这段代码正常执行 ``` `for ... else` 语法: ```plaintext for 临时变量 in 序列: 重复执行的代码 else: 循环正常结束之后要执行的代码 ``` 同理:如果是 `break` 终止循环的情况,`else` 下方缩进的代码将不执行;如果是 `continue`,则不会受其影响 ```python str = 'liang' for i in str: if i == 'a': break print(i) else: print('循环正常结束执行的else代码') # 不会执行 ``` #### 6. 字符串 --- 字符串是 Python 中最常用的数据类型。我们一般使用引号来创建字符串。创建字符串很简单,只要为变量分配一个值即可 字符串的定义方式: ```python # 单引号 a = 'hello world' print(type(a)) # 双引号 b = "liang" print(type(b)) # 三引号 c = '''tom''' print(type(c)) d = """zhang""" print(type(d)) e = """I am tom """ print(e) # 输出结果也会换行 # 处理引号转义 f = 'I\'m tom' print(f) ``` 字符串的输出: ```python name = 'liang' print(f"我的名字是 {name}") print("我的名字是 %s" % name) ``` “下标” 又叫 “索引”,也就是编号。下标的作用就是通过下标快速找到对应的数据(注意:下标从 0 开始) 切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作 语法格式: + 不包含结束位置下标对应的数据,正负整数均可 + 步长是选取间隔,正负整数均可,可以不写,默认步长为 1 ```plaintext 序列[开始位置下标:结束位置下标] 序列[开始位置下标:结束位置下标:步长] ``` 使用示例: ```python str = 'abcdefg' # 得到整个字符串的数据 print(str) # abcdefg # 下标得到的是下标为某个数字的数据 print(str[2]) # c # 得到 abc 这3个数据 print(str[0:3]) # abc # 步长截取,每3个截取一次 print(str[0:5:3]) # ad # 如果不写开始,默认从0开始 print(str[:4]) # abcd # 如果不写结束,表示选取到最后 print(str[2:]) # cdefg # 如果不写开始和结束,表示选取所有 print(str[:]) # abcdefg # 如果步长为负数,表示倒叙选取 print(str[::-1]) # gfedcba # 坐标取负数 print(str[-4:-1]) # def ``` 字符串的常用操作方法有查找、修改和判断三大类 修改字符串:指的就是通过函数的形式修改字符串中的数据 `replace()`:替换。语法格式: ```plaintext 字符串序列.replace(旧子串, 新子串, 替换次数) ``` 使用示例: ```python # 调用 replace 函数后,发现原字符串数据并没有发生改变,修改后的数据是 replace 函数的返回值 # 说明字符串是不可变类型 # 数据是否可以改变划分为 可变类型 和 不可变类型 str = 'hello world and liang and king and python' print(str.replace('and', 'or')) # hello world or liang or king or python print(str.replace('and', 'or', 2)) # hello world or liang or king and python ``` `split()`:按照指定字符分割字符串。语法格式: ```plaintext 字符串序列.split(分割字符, 分割次数) ``` 使用示例: ```python # split() 分割字符串,返回一个列表,丢失分割字符 str = 'hello world and liang and king and python' print(str.split('and')) # ['hello world ', ' liang ', ' king ', ' python'] print(str.split('and', 2)) # ['hello world ', ' liang ', ' king and python'] ``` `join()`:按照指定字符分割字符串。语法格式: ```plaintext 字符或子串.join(多字符串组成的序列) ``` 使用示例: ```python # join() 合并列表里面的字符串数据为一个大字符串 myList = ['aa', 'bb', 'cc'] newStr = ','.join(myList) print(newStr) # aa,bb,cc ``` 其它字符串操作函数,非重点,了解即可 ```python str = 'how are YOU ?' # capitalize() 将字符串第一个字符转为大写,其它字符全都小写 print(str.capitalize()) # How are you ? (YOU 被转位小写了) # title() 将字符串每个单词首字母转为大写 print(str.title()) # How Are You ? # lower() 将字符串全部转为小写 print(str.lower()) # how are you ? # upper() 将字符串全部转为大写 print(str.upper()) # HOW ARE YOU ? greet = ' how old are you ' print(greet.lstrip()) # 删除左侧空白字符串 print(greet.rstrip()) # 删除右侧空白字符串 print(greet.strip()) # 删除两侧空白字符串 ``` 字符串判断相关操作方法: ```python str = 'how are you' # 判断字符串是否以某个子串开头 print(str.startswith('how')) # True print(str.startswith('are')) # False # 判断字符串是否以某个子串结尾 print(str.endswith('are')) # False print(str.endswith('you')) # True # isdigit() 判断字符串是不是纯数字 str1 = '3' str2 = '3.14' str3 = '3.14y' print(str1.isdigit()) # True print(str2.isdigit()) # False print(str3.isdigit()) # False # isalnum() 判断是不是数字+字母 print('123'.isalnum()) # True print('123a'.isalnum()) # False print('3.14'.isalnum()) # False ``` #### 7. 列表 --- 列表的格式(列表可以一次性存储多个数据,且可以为不同数据类型): ```plaintext [数据1, 数据2, 数据3...] ``` 可以通过下标或函数获取列表的数据 `index()` 函数语法格式: ```plaintext 列表序列.index(数据, 开始位置, 结束位置下标) ``` 使用示例: ```python name = ['Tom', 'King', 'Rose', 'King', 'Liang'] # 按照下标获取数据 print(name[0]) # Tom print(name[1]) # King print(name[2]) # Rose # 通过函数获取列表数据 # index() 如果查找的数据不存在会报错 print(name.index('King', 0, 2)) # 1 # 统计指定数据在列表中出现的次数 print(name.count('King')) # 2 # 获取列表长度,也就是列表中数据的个数 print(len(name)) # 5 ``` 判断数据是否在列表中 ```python name = ['Tom', 'King', 'Rose'] # in 判断指定数据是否在列表中,在返回 True print('King' in name) # True print('liang' in name) # False # not in 判断指定数据不在列表中,不在返回 True print('King' not in name) # False print('liang' not in name) # True ``` 使用示例: ```python name = input('请输入您搜索的名字: ') name_list = ['Tom', 'King', 'Rose'] if name in name_list: print(f'您输入的:{name},已经存在,无法注册') else: print(f'您输入的:{name},不存在,可以注册') ``` 增加指定数据到列表中 ```python name = ['Tom', 'King'] # append() 在列表结尾追加数据 name.append('liang') print(name) # ['Tom', 'King', 'liang'] # insert(下标, 数据) 在指定位置追加数据 name.insert(1, 'css') # ['Tom', 'css', 'King', 'liang'] print(name) ``` 删除列表或列表数据 ```python name = ['Tom', 'King', 'Rose'] # del 删除列表 # 1.下面两种写法都可以 # del name # del(name) # print(name) # NameError: name 'name' is not defined # 2.也可以删除指定下标的数据 del name[0] print(name) # ['King', 'Rose'] # pop(下标) 删除指定下标的数据,如果不指定下标,默认删除最后一个数据,返回值是被删除的数据 item = name.pop(1) print(item) # Rose print(name) # ['King'] # remove(数据) 删除指定数据 user = ['html', 'css', 'js'] user.remove('css') print(user) # ['html', 'js'] # clear() 清空列表 admin = ['king', 'aria'] admin.clear() print(admin) # [] ``` 修改列表中的数据 ```python name = ['Tom', 'King', 'Rose'] # 修改指定下标的数据 name[1] = 'Python' print(name) # ['Tom', 'Python', 'Rose'] # reverse() 列表数据反转 name.reverse() print(name) # ['Rose', 'Python', 'Tom'] # sort() 排序:升序、降序 num = [2, 5, 4, 3, 1] # num.sort() # 升序(默认值) num.sort(reverse=True) # 降序 print(num) # [5, 4, 3, 2, 1] ``` 复制列表 ```python # copy() 复制列表 name_list = ['Tom', 'King', 'Rose'] list1 = name_list.copy() print(list1) print(name_list) # 修改原列表,不会影响复制出来的新列表 name_list.pop() print(list1) print(name_list) ``` 列表的循环遍历 ```python # while 循环遍历 i = 0 while i < len(name_list): print(name_list[i]) i += 1 # for 循环遍历 for i in name_list: print(i) ```` 列表嵌套:指的就是一个列表里面包含了其它的子列表 应用场景:要存储班级一、二、三 3个班级学生姓名,且每个班级的学生姓名在一个列表 ```python name_list = [['小明','小红', '小绿'], ['Tom', 'King', 'Rose'], ['张三', '李四', '王五']] # 思考:如何查找到数据 “李四” ? # 按下标找到李四所在的列表,然后从李四所在的列表里面再按下标找到数据李四 print(name_list[2][1]) ``` 随机分配办公室,需求:有3个办公室、8位老师,将8位老师随机分配到3个办公室 ```python import random # 1.准备数据 teachers = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] offices = [[], [], []] # 2.分配老师到办公室,取每个老师放到办公室列表 for i in teachers: offices[random.randint(0, 2)].append(i) # 3.查看分配结果 print(offices) ``` #### 8. 元组 --- 元组的应用场景 思考:如果想要存储多个数据,但是这些数据是不能修改的,怎么做 ? 回答:列表 ?列表可以一次性存储多个数据,但是列表中的数据允许更改 ```python list1 = ['html', 'css', 'js'] list1[1] = 'vue' print(list1) ``` 一个元祖可以存储多个数据,元祖内的数据是不能修改的 元组特点:定义元祖使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型 ```python # 多个数据元组 t1 = (10, 20, 30) # 单个数据元组 t2 = (10,) ``` 如果定义的元祖只有一个数据,那么这个数据后面最好也添加逗号,否则数据类型是唯一的这个数据的数据类型 ```python t2 = (10,) print(type(t2)) # tuple t3 = (10) print(type(t3)) # int t4 = ('hello') print(type(t4)) # str ``` 元组数据不支持修改,只支持查找 ```python t1 = ('aa', 'bb', 'cc', 'bb') # 按下标获取数据 print(t1[0]) # aa # index() 查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的 index 方法相同 print(t1.index('cc')) # 2 # count() 统计某个数据在当前元组出现的次数 print(t1.count('bb')) # 2 # len() 统计元组中数据的个数 print(len(t1)) # 4 ``` 元组内的直接数据如果修改则立即报错 ```python t1 = ('aa', 'bb', 'cc', 'bb') t1[0] = 'ee' # TypeError: 'tuple' object does not support item assignment ``` 但是如果元组里面有列表,修改列表里面的数据则是支持的,故自觉很重要 ```python t1 = ('aa', 'bb', ['cc', 'bb']) t1[2][1] = 'ee' print(t1) # ('aa', 'bb', ['cc', 'ee']) ``` #### 9. 字典 --- 字典的应用场景 思考1:如果有多个数据,例如:`'Tom','男', 20` 如何快速存储 ? 答:首选,肯定会先想到使用列表存储 ```python user = ['Tom', '男', 20] ``` 思考2:如何查找到数据 `'Tom'` ? 答:查找到下标为 0 的数据即可 ```python print(user[0]) ``` 思考3:如果将来数据顺序发生变化,如下所示,还能用 `user[0]` 访问到数据 'Tom' 吗 ? 答:不能,数据 `'Tom'` 此时下标为 2 ```python user = ['男', 20, 'Tom'] ``` 思考4:数据顺序发生变化,每个数据的下标也会随之变化,如何保证数据顺序变化前后能使用同一标准查找数据呢 ? 答:字典。字典里面的数据是以键值对形式出现,字典数据和数据顺序没有关系,即字典不支持下标,后期无论数据如何变化,只需要按照对应的键的名字查找数据即可 创建字典的语法: + 符号为大括号 + 数据为键值对形式出现 + 各个键值对之间用逗号隔开 ```python # 有数据字典 dict1 = { 'name': 'liang', 'age': 18, 'gender': '男' } # 空字典 dict2 = {} dict3 = dict() ``` 字典的新增和修改操作(如果 key 存在则修改对应的值,如果 key 不存在则新增此键值对) ```plaintext 字典序列[key] = 值 ``` ```python dict1 = { 'name': 'liang', 'age': 18 } # 新增 dict1['id'] = 100 # 修改 dict1['name'] = 'Tom' print(dict1) ``` 字典的删除数据操作 ```python dict1 = { 'name': 'liang', 'age': 18, 'gender': '男' } # del/del() 删除字典或删除字典中的指定键值对 del dict1['name'] print(dict1) # {'age': 18, 'gender': '男'} # 删除字典 # dict2 = { 'id': 1, 'name': 'liang' } # del(dict2) # print(dict2) # NameError: name 'dict2' is not defined. # clear() 清空字典 dict1.clear() print(dict1) # {} ``` 字典数据查找操作 ```python dict1 = { 'name': 'liang', 'age': 18, 'gender': '男' } # 1.key 值查找(如果 key 不存在会报错) print(dict1['name']) # 2.函数 # 使用 get() 函数查找,语法:dict1.get(key, 默认值) # 如果当前查找的 key 不存在也不会报错,会返回默认值 None print(dict1.get('age')) print(dict1.get('email', '123@qq.com')) # keys() 查看字典中所有的 key,返回可迭代对象 print(dict1.keys()) # values() 查看字典中所有的 value,返回可迭代对象 print(dict1.values()) # items() 查看字典中所有的键值对,每个键值对是一个元组 print(dict1.items()) # dict_items([('name', 'liang'), ('age', 18), ('gender', '男')]) ``` 字典的循环遍历 ```python dict1 = { 'name': 'liang', 'age': 18, 'gender': '男' } # 遍历字典的 key for key in dict1.keys(): print(key) # 遍历字典的 value for value in dict1.values(): print(value) # 遍历字典的元素 for item in dict1.items(): print(item) # 遍历字典的键值对 # dict1.items() 返回可迭代对象,内部是元组,元组有2个数据 for key, value in dict1.items(): print(f"{key}, {value}") ``` #### 10. 集合 --- 创建集合使用 `{}` 或 `set()`,但是如果要使用空集合只能使用 `set()`,因为 `{}` 用来创建空字典 + 集合的特点:数据不重复 ```python # 1.创建有数据的集合 # 集合是没有顺序的,所以它不支持下标操作 s1 = { 10, 20, 30, 40, 50 } print(s1) # {50, 20, 40, 10, 30} # 集合数据去重功能 s2 = {10, 30, 20, 10, 30, 40, 30, 50 } print(s2) # {50, 20, 40, 10, 30} # 使用 set() 创建集合,数据也是没有顺序的 s3 = set('abcdefg') print(s3) # {'d', 'b', 'f', 'g', 'e', 'a', 'c'} # 2.创建空集合:set() s4 = set() print(s4) # set() print(type(s4)) # <class 'set'> s5 = {} print(type(s5)) # <class 'dict'> ``` 集合常见操作方法 增加数据 ```python # 因为集合有去重功能,所以当向集合内追加的数据集合内已有时,则不进行任何操作 s1 = {10, 20} s1.add(30) # 集合内没有改数据,追加成功 s1.add(10) # 集合内已有时该数据,不进行任何操作 print(s1) # update() 追加的数据是序列 s2 = {10, 20} # s2.update(30) # 报错:TypeError: 'int' object is not iterable s2.update([20, 30, 40]) s2.update('abc') print(s2) # {'a', 'c', 40, 10, 'b', 20, 30} ``` 删除数据 ```python s1 = {10, 20, 30, 40, 50} # remove() 函数集合中的指定数据,如果数据不存在则报错 s1.remove(10) # discard() 函数集合中的指定数据,如果数据不存在也不会报错 s1.discard(80) s1.discard(30) print(s1) # pop() 随机删除某个数据,并返回这个数据 del_item = s1.pop() print(del_item) print(s1) ``` 判断数据是否在集合中 ```python s1 = {10, 20, 30, 40, 50} # in 判断数据是否在集合中 print(10 in s1) # True # not in 判断数据是否不在集合中 print(10 not in s1) # False ``` #### 11. 公共操作 --- 公共操作指的是前面学习过的数据序列基本都支持的操作(运算符/公共方法/容器类型转换) 运算符 | 运算符 | 描述 | 支持的容器类型 | | ------------ | ------------ | ------------ | | + | 合并 | 字符串、列表、元组 | | \* | 复制 | 字符串、列表、元组 | | in | 元素是否存在 | 字符串、列表、元组、字典 | | not in | 元素是否不存在 | 字符串、列表、元组、字典 | 合并操作 ```python str1 = 'hello ' str2 = 'world' list1 = [1, 2] list2 = [10, 20] t1 = (1, 2) t2 = (10, 20) dict1 = { 'name': 'liang' } dict2 = { 'age': 30 } # + 合并 print(str1 + str2) # hello world print(list1 + list2) # [1, 2, 10, 20] print(t1 + t2) # (1, 2, 10, 20) # print(dict1 + dict2) # TypeError: unsupported operand type(s) for +: 'dict' and 'dict' ``` 复制操作 ```python str1 = 'a' list1 = ['hello'] t1 = ('world',) # * 复制 print(str1 * 5) # aaaaa print(list1 * 5) # ['hello', 'hello', 'hello', 'hello', 'hello'] print(t1 * 5) # ('world', 'world', 'world', 'world', 'world') ``` 判断元素是否存在数据序列中 ```python str1 = 'abcd' list1 = [10, 20, 30, 40] t1 = (100, 200, 300, 400) dict1 = { 'name': 'python', 'age': 20 } # 字符串 print('c' in str1) # True print('c' not in str1) # False # 列表 print(10 in list1) # True print(50 not in list1) # True # 元组 print(200 in t1) # True print(200 not in t1) # False # 字典 print('name' in dict1.keys()) # True print('gender' not in dict1.keys()) # True ``` 公共方法 | 函数 | 描述 | | ------------ | ------------ | | len() | 计算容器中元素个数 | | del 或 del() | 删除 | | max() | 获取容器中元素最大值 | | min() | 获取容器中元素最小值 | | range(start, end, step) | 生成从 start 到 end 的数字,步长为 step,供 for 循环使用 | | enumerate() | 用于将一个可遍历的数据对象组合为一个索引序列,同时列出数据和数据下标 | ```python str1 = 'abcdefg' list1 = [10, 20, 30, 40, 50] t1 = (10, 20, 30, 40, 50) s1 = {10, 20, 30, 40, 50} dict1 = { 'name': 'python', 'age': 20 } # len() 获取元素个数 print(len(str1)) print(len(list1)) print(len(t1)) print(len(s1)) print(len(dict1)) # del 删除目标 或 del(目标) # del str1 # print(str1) # del s1 # print(s1) # del list1 del list1[2] print(list1) # del dict1 del dict1['name'] print(dict1) # 获取容器中的最大值和最小值 print(max(list1)) print(min(list1)) ``` `range(start, end, step)`:生成从 start 到 end 的数字,步长为 step,供 for 循环使用 ```python # 注意:range() 生成的序列不包含 end 数字 # 如果不写开始,默认从 0 开始 # 如果不写步长,默认为 1 for i in range(1, 5, 1): print(i) # 1 2 3 4 for i in range(1, 10, 2): print(i) # 1 3 5 7 9 for i in range(5): print(i) # 0 1 2 3 4 ``` `enumerate()` 语法格式: + 注意:start 参数用来设置遍历数据的下标的起始值,默认为 0 ```plaintext enumerate(可遍历对象, start=0) ``` 快速体验 ```python list1 = ['a', 'b', 'c', 'd', 'e'] # enumerate() 返回结果是元组 # 元组第一个数据是原迭代对象的数据对应的下标,元组的第二个数据是原迭代对象的数据 enum = enumerate(list1, start=1) for index, item in enum: print(f'{index}, {item}') ``` 容器类型转换 ```python list1 = [10, 20, 30, 20, 40, 50] s1 = {100, 300, 200, 500} t1 = ('a', 'b', 'c', 'd', 'e') # tuple() 将某个序列转换为元组 print(tuple(list1)) # (10, 20, 30, 20, 40, 50) print(tuple(s1)) # (200, 100, 500, 300) # list() 转换为列表 print(list(s1)) # [200, 100, 500, 300] print(list(t1)) # ['a', 'b', 'c', 'd', 'e'] # set() 转换为集合 # 1.集合可以快速完成列表去重 # 2.集合不支持下标 print(set(list1)) # {40, 10, 50, 20, 30} print(set(t1)) # {'b', 'e', 'a', 'c', 'd'} ``` #### 12. 推导式(生成式) --- 只有列表、字典、集合有推导式,推导式又叫生成式(作用:简化代码) 列表推导式:用一个表达式创建一个有规律的列表或控制一个有规律列表 ```python # 需求:循环实现 10 以内的数字追加到列表中 # while 循环实现 i = 0 list1 = [] while i < 10: list1.append(i) i += 1 print(list1) # for 循环实现 list2 = [] for i in range(10): list2.append(i) print(list2) # 列表推导式实现 list3 = [i for i in range(10)] print(list3) ``` 带 if 的列表推导式 ```python # 需求:创建 0-10 的偶数列表 # 方法一:range() 步长实现 list1 = [i for i in range(10)] print(list1) # 方法二:if 实现 list2 = [i for i in range(10) if i % 2 == 0] print(list2) # [0, 2, 4, 6, 8] ``` 多个 for 循环实现列表推导式 ```python # 需求:创建列表 [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] # 普通写法 list1 = [] for i in range(1, 3): for j in range(3): list1.append((i, j)) print(list1) # 推导式写法 list2 = [(i, j) for i in range(1, 3) for j in range(3)] print(list2) ``` 思考:如果有两个列表,如何快速合并为一个字典 ? 答:字典推导式。字典推导式作用:快速合并列表为字典或提取字典中目标数据 ```python list1 = ['name', 'age', 'gender'] list2 = ['Tom', 20, 'man'] ``` 快速体验 ```python # 创建一个字典:字典key是1-5数字,value是这个数字的2次方 dict1 = {i: i**2 for i in range(1, 5)} print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16} # 将两个列表合并为一个字典 list1 = ['name', 'age', 'gender'] list2 = ['Tom', 20, 'man'] dict2 = {list1[i]: list2[i] for i in range(len(list1))} print(dict2) # {'name': 'Tom', 'age': 20, 'gender': 'man'} # 提取字典中目标数据 counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99} # 需求:提取上述电脑数量大于等于200的字典数据 count1 = {key: value for key, value in counts.items() if value >= 200} print(count1) # {'MBP': 268, 'DELL': 201} ``` 集合推导式 需求:创建一个集合,数据为下方列表的2次方 ```python list1 = [2, 2, 3] ``` 快速体验 ```python # 集合有数据去重功能 list1 = [2, 2, 3] set1 = {i ** 2 for i in list1} print(set1) # {9, 4} ``` 总结:推导式的作用就是简化代码,推导式写法: ```plaintext # 列表推导式 [xx for xx in range()] # 字典推导式 {xx1:xx2 for ... in ...} # 集合推导式 {xx for xx in ...} ``` #### 13. 函数的用法 --- 函数就是将一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求 + 函数在开发过程中,可以更高效的实现代码复用 函数的使用步骤:定义函数、调用函数 定义函数: ```plaintext def 函数名(参数): 代码1 代码2 ...... ``` 调用函数 ```plaintext 函数名(参数) ``` 注意: + 不同的需求,参数可有可无 + 在 Python 中,函数必须先定义后使用 快速体验 ```python def info_print(): print('hello world') print('你好,世界') info_print() ``` 函数的参数 ```python # 形参:函数定义的参数 def add(a, b): print(f'a + b = {a + b}') # 实参:调用函数时传入的数据 add(2, 3) ``` 函数的返回值 ```python def add(a, b): return a + b # 函数的返回值 # 使用变量保存函数的返回值 result = add(2, 3) print(result) ``` 定义函数的说明文档: ```plaintext def 函数名(参数): """ 说明文档的位置 """ 代码 ...... ``` 查看函数的说明文档 ```plaintext help(函数名) ``` 使用示例 ```python # help() 函数作用:查看函数的说明文档(函数的解释说明的信息) help(len) # 函数说明文档的使用 def sum(a,b): """求和函数""" return a + b help(sum) # 函数说明文档的高级使用 def add(a,b): """ 累加参数 :param a:参数1 :param b:参数2 :return:累加和 """ return a + b help(add) ``` 函数嵌套调用:一个函数里面又调用了另外一个函数 ```python def testA(): print('-- testA 函数开始 --') print('-- testA 函数结束 --') def testB(): print('-- testB 函数开始 --') testA() print('-- testB 函数结束 --') testB() # 输出结果 # -- testB 函数开始 -- # -- testA 函数开始 -- # -- testA 函数结束 -- # -- testB 函数结束 -- ``` 练习题小案例: ```python # 打印n条横线 def line(): print('-' * 10) def print_lines(num): i = 0 while i < num: line() i += 1 print_lines(3) # 任意三个数求和 def sum_num(a, b, c): return a + b + c print(sum_num(5, 6, 7)) # 任意三个数的平均值 def average(a, b, c): sum = sum_num(a,b,c) return sum / 3 print(average(1,3, 5)) ``` #### 14. 函数进阶用法 --- 函数进阶内容学习目标: + 变量作用域 + 多函数程序执行流程 + 函数的返回值 + 函数的参数 + 拆包和交换两个变量的值 + 引用 + 可变和不可变类型 变量作用域:指的是变量生效的范围,主要分为两类:局部变量和全局变量 局部变量:定义在函数体内部的变量,即只在函数体内部生效 局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量 ```python # 变量 a 是定义在函数内部的变量,在函数外部访问则立即报错 def test(): a = 100 print(a) # 100 test() print(a) # 报错:NameError: name 'a' is not defined ``` 全局变量:指的是在函数体内、外都能生效的变量 思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办 ? 答:将这个数据存储在一个全局变量里面 ```python a = 100 def test1(): print(a) # 访问全局变量a,并打印变量a存储的数据 def test2(): print(a) # 访问全局变量a,并打印变量a存储的数据 test1() test2() ``` 在函数体内部修改全局变量 ```python a = 10 b = 20 def test(): a = 30 # 这是在内部定义了一个局部变量 global b # global 关键字声明 b 是全局变量 b = 40 # 此时修改的是全局变量 b print(a) # 30 print(b) # 40 test() print(a) # 10 print(b) # 40 ``` 多函数程序执行流程 实际开发过程中,一个程序往往由多个函数组成(后面知识中会讲解类),并且多个函数共享某些数据,如下所示: ```python # 定义全局变量 glo_num = 0 def test1(): global glo_num glo_num = 100 # 修改全局变量 def test2(): # 调用 test1() 函数中修改后的全局变量 print(glo_num) # 100 # 调用 test1() 执行函数内部代码,声明和修改全局变量 test1() # 调用 test2() 执行函数内部代码,打印 test2() ``` 函数的返回值 ```python # 返回值作为参数传递 def test1(): return 50 def test2(num): print(num) # 先得到 test1() 函数的返回值,再把这个返回值传入 test2() result = test1() test2(result) # 一个函数多个返回值的写法 # return a,b 写法返回多个数据的时候,默认是元组类型 # return 后面可以连接列表、元组或字典,以返回多个值 def return_num(): # return 1,2 # 返回的是元组 # return [10, 20], [30, 40] return {'name': 'liang'}, 10 result = return_num() print(result) ``` 函数的参数写法 + 位置参数:调用函数时根据函数定义的参数位置来传递参数 + 关键字参数:通过 “键=值” 形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求 + 缺省参数:缺省参数也叫默认参数,用于定义参数的默认值(所有位置参数必须出现在默认参数前) + 不定长参数:不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数的场景(不传参也可以) ```python # 位置参数:传递和定义参数的顺序及个数必须一致 def user_info(name, age, gender): print(f"您的名字是{name},年龄是{age},性别是{gender}") user_info('liang', '20', '男') # 关键字参数:通过 “键=值” 形式指定 def teacher(name, age, gender): print(f"您的名字是{name},年龄是{age},性别是{gender}") # 函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序 teacher('liang', age=20, gender='男') teacher('liang', gender='男', age=18) teacher(gender='男', age=18, name='python') # 缺省参数:参数的默认值 def mate(name, age, gender = '男'): print(f"您的名字是{name},年龄是{age},性别是{gender}") mate('Tom', 20) mate('Rose', 20, '女') # 1.可变参数 - 包裹位置传递 # 所有传入的参数都会被变量 args 收集,它会根据传进参数的位置合并为一个元组 def test1(*args): print(args) test1('Tom') test1('Tom', 18) # 2.可变参数 - 包裹关键字传递 # 所有传入的参数都会被变量 kwargs 收集,它会根据传进参数的位置合并为一个字段 def test2(**kwargs): print(kwargs) test2(name='Tom', age=18, id=100) # 综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程 ``` 拆包和交换变量值 ```python # 拆包元组数据 def return_num(): return 100, 200 num1, num2 = return_num() print(num1, num2) # 拆包字典数据 dict1 = {'name': 'liang', 'age': 18} name, age = dict1.values() print(name, age) # 交换变量值 a, b = 1, 2 print(a, b) a, b = b, a print(a, b) ``` 引用:在 Python 中,值是靠引用来传递的。 我们可以用 `id()` 来判断两个变量是否为同一个值的引用。可以将 id 值理解为那块内存地址的标识 ```python # int 是不可变类型 a = 1 b = a print(b) # 1 print(id(a)) # 4343849328 print(id(b)) # 4343849328 a = 2 print(b) print(id(a)) # 4343849360(发生变化,说明 int 是不可变类型) print(id(b)) # 4343849328 # list 列表是可变类型 aa = [10, 20] bb = aa print(id(aa)) # 4366350656 print(id(bb)) # 4366350656 aa.append(30) print(id(aa)) # 4366350656 print(id(bb)) # 4366350656 ``` 可变类型和不可变类型:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变 + 可变类型:列表、字典、集合 + 不可变类型:整型、浮点型、字符串、元组 #### 15. 学员管理系统(函数案例) --- 学员管理系统需求:进入系统显示系统功能界面,功能如下: + 1、添加学员 + 2、删除学员 + 3、修改学员信息 + 4、查询学员信息 + 5、显示所有学员信息 + 6、退出系统 系统共6个功能,用户根据自己需求选取 步骤分析: + 1、显示功能界面 + 2、用户输入功能序号 + 3、根据用户输入的功能序号,执行不同的功能(函数) + 定义函数 + 调用函数 ```python # 定义显示功能界面的函数 def info_print(): print('-------- 请选择功能 --------') print('1、添加学员') print('2、删除学员') print('3、修改学员信息') print('4、查询学员信息') print('5、显示所有学员信息') print('6、退出系统') print('-' * 26) # 存储所有学员信息 info = [] # 添加学员信息 def add_info(): """添加学员""" # 1.获取用户输入 new_id = input('请输入学号:') new_name = input('请输入学员姓名:') # 2.判断学员是否已经存在 global info for i in info: if i['id'] == new_id: print('此学员已经存在') return print('添加学员成功') info_dict = {'id': new_id, 'name': new_name} info.append(info_dict) # 删除学员信息 def del_info(): """删除学员""" id = input('请输入删除的学号:') global info for i in info: if i['id'] == id: info.remove(i) print('删除学员成功') break else: print(f'学员:{id} 不存在') # 修改学员信息 def update_info(): """修改学员信息""" id = input('请输入修改的学号:') global info for i in info: if i['id'] == id: new_name = input('请输入新的姓名:') i['name'] = new_name print('修改学员成功') break else: print(f'学员:{id} 不存在') # 查询学员信息 def search_info(): search_name = input('请输入学员姓名:') global info for i in info: if i['name'] == search_name: print('查询到学员', i) break else: print(f'学员:{search_name} 不存在,查无此人') # 查看所有学员信息 def all_info(): print(info) # 系统功能需要循环使用,直到用户输入 6,才退出系统 while True: print('学员信息:', info) # 1.显示功能界面 info_print() # 2.用户输入功能序号 user_num = int(input('请输入功能序号:')) # 3.按照用户输入的功能序号,执行不同的功能(函数) if user_num == 1: add_info() elif user_num == 2: del_info() elif user_num == 3: update_info() elif user_num == 4: search_info() elif user_num == 5: all_info() elif user_num == 6: exit_flag = input('确定要退出吗? yes or no\n') if exit_flag == 'yes': print('退出系统成功') break else: print('您输入的功能序号有误') ``` #### 16. 递归 --- 递归是一种编程思想,应用场景: + 日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现 + 很多算法都离不开递归,例如:快速排序 递归的特点:函数内部自己调用自己、必须有出口 ```python # 需求:获取5以内数字的累加和 def sum(num): if num == 1: return 1 return num + sum(num - 1) print(sum(5)) # 5 + 4 + 3 + 2 + 1 = 15 ``` #### 17. lambda 表达式 --- lambda 应用场景:如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda 简化 lambda 语法: + lambda 表达式的参数可有可无,函数的参数在 lambda 表达式中完全适用 + lambda 表达式能接收任何数量的参数,但只能返回一个表达式的值 ```plaintext lambda 参数列表 : 表达式 ``` 快速体验 ```python # 1.函数 def fn1(): return 100 print(fn1()) # 2.lambda 匿名函数 # lambda 参数列表 : 表达式 fn2 = lambda: 200 print(fn2) # 输出的是 lambda 内存地址 <function <lambda> at 0x10060c4a0> print(fn2()) # 需求:计算 a + b # 普通函数 def add(a, b): return a + b print(add(1, 2)) # lambda 表达式 sum = lambda a, b: a + b print(sum(1, 2)) ``` lambda 的参数形式 ```python # 无参数 fn1 = lambda: 10 # 一个参数 fn2 = lambda a: a # 默认参数 fn3 = lambda a, b = 30: a + b # 可变参数-包裹位置传递 fn4 = lambda *args: args # 可变参数-包裹关键字传递 fn5 = lambda **kwargs: kwargs print(fn1()) print(fn2(20)) print(fn3(100)) print(fn4('a', 'b')) print(fn5(name='liang', age=20)) ``` lambda 的应用 ```python # 1.带判断的 lambda fn1 = lambda a,b: a if a > b else b print(fn1(1000, 500)) # 2.列表数据按字典key的值排序 students = [ {'name': 'Tom', 'age': 20}, {'name': 'Rose', 'age': 19}, {'name': 'Jack', 'age': 22}, ] # 按 name 值升序排列 students.sort(key=lambda x:x['name']) print(students) # 按 name 值降序排列 students.sort(key=lambda x:x['name'], reverse=True) print(students) ``` #### 18. 高阶函数 --- 把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式 ```python # 在 Python 中,abs() 函数可以完成对数字求绝对值计算 print(abs(-10)) # 10 # round() 函数可以完成对数字的四舍五入计算 print(round(1.2)) # 1 print(round(1.9)) # 2 # 需求:任意两个数字,按照指定要求整理数字后再进行求和计算 # 注意:两种方法对比之后,发现方法2的代码会更加简洁,函数灵活性更高 # 函数式编程大量使用函数,减少了代码量的重复,因此程序比较短,开发速度较快 # 方法1 def add_num(a, b): return abs(a) + abs(b) # 方法2 def sum_num(a, b, f): return f(a) + f(b) print(add_num(5, -6)) print(sum_num(5, -6, abs)) ``` 内置高阶函数 ```python # map(func,lst) 将传入的函数变量 func 作用到 lst 变量的每个元素中,返回新的列表 list1 = [1, 2, 3, 4, 5] def func(x): return x ** 2 result = map(func, list1) print(result) # <map object at 0x103140df0> print(list(result)) # [1, 4, 9, 16, 25] # reduce(func, lst) 其中 func 必须有两个参数。 # 每次 func 计算的结果继续和序列的下一个元素做累积计算 import functools # 需要导入模块 list2 = [1, 2, 3, 4, 5] def func2(a,b): return a + b result2 = functools.reduce(func2, list2) print(result2) # 15 # filter(func, lst) 用于过滤序列,过滤掉不符合条件的元素 # 返回一个 filter 对象,如果要转换为列表,可以使用 list() 来转换 list3 = [1, 2, 3, 4, 5] def func3(x): return x % 2 == 0 result3 = filter(func3, list3) print(list(result3)) # [2, 4] ``` #### 19. 文件操作 --- 学习目标: + 文件操作的作用 + 文件的基本操作(打开/读写/关闭) + 文件备份 + 文件和文件夹的操作 思考:文件操作包含什么 ? 答:打开、关闭、读写、复制 思考:文件操作的作用是什么 ? 答:读取内容、写入内容、备份内容 总结:文件操作的作用就是把一些内容存储放起来,可以让程序下一次执行的时候直接使用,而不必重新制造一份 文件的基本操作:打开文件、读写操作、关闭文件 在 python,使用 open 函数,可以打开一个已经存在的文件,或者创建一个新的文件 + name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径) + mode:设置打开文件的模式(访问模式):只读、写入、追加等 ```plaintext open(name, mode) ``` 打开文件模式(`read` 读取 `write` 写入 `binary` 二进制 `append` 追加 \+ 表示可读可写): | 模式 | 描述 | | ------------ | ------------ | | r | 以只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式 | | rb | 以二进制格式打开一个文件用于只读。文件的指针将会放在文件的开头,这是默认模式 | | r+ | 打开一个文件用于读写。文件指针将会放在文件的开头 | | rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头 | | w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从头开始编辑;如果该文件不存在,则创建新文件 | | wb | 以二进制格式打开一个文件只用于写入。若文件存在就打开文件;若文件不存在,则创建新文件 | | w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从头开始编辑;如果该文件不存在,则创建新文件 | | wb+ | 以二进制格式打开一个文件用于读写。若文件存在就打开文件;若文件不存在,则创建新文件 | | a | 打开一个文件用于追加。打开文件且指针放在文件末尾;若文件不存在,则创建新文件 | | ab | 以二进制格式打开一个文件用于追加。打开文件且指针放在文件末尾;若文件不存在,则创建新文件 | | a+ | 打开一个文件用于读写。打开文件且指针放在文件末尾;若文件不存在,则创建新文件 | | ab+ | 以二进制格式打开一个文件用于追加。打开文件且指针放在文件末尾;若文件不存在,则创建新文件 | 快速体验 ```python # 打开文件 f = open('test.txt', 'w') # 读写操作 f.write('aaa') # 关闭文件 f.close() ``` 使用示例 ```python # r 只读:如果文件不存在,会报错,因为没有写入权限 f = open('test1.txt', 'r') # 关闭文件 f.close() # w 只写:如果文件不存在,新建文件。若文件存在,执行写入,会覆盖原内容 f2 = open('1.txt', 'w') f2.write('bbb') f2.close() # a 追加:写入内容不会覆盖原内容 f2 = open('2.txt', 'a') f2.write('bbb') f2.close() # 访问模式是否可以省略 ? # 答:可以省略,默认访问模式是 r f3 = open('3.txt') # 文件不存在会报错 # f3 = open('2.txt') # 文件存在不会报错 f3.close() ``` 读取文件内容 `read(num)`:num 表示要从文件中读取的数据长度(单位是字节),如果没有传入 num,那么就表示读取文件中所有数据 ```plaintext 文件对象.read(num) ``` 准备好一个文件 `test.txt`,文件内容: ```plaintext aaaaa bbbbb ccccc ddddd eeeee ``` 代码示例: ```python # 打开文件 f = open('test.txt', 'r') # read() 不写参数表示读取所有 # print(f.read()) # 文件内容如果换行,底层有\n,会有字节占位,导致 read 书写参数读取出来的眼睛看到的个数和参数值不匹配 print(f.read(10)) # 关闭文件 f.close() ``` `readlines()` 按照行的方式把整个文件内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素 ```python f = open('test.txt') content = f.readlines() print(content) # ['aaaaa\n', 'bbbbb\n', 'ccccc\n', 'ddddd\n', 'eeeee'] f.close() ``` `readline()` 一次读取一行内容 ```python f = open('test.txt') content = f.readline() print(f'第一行:{content}') content = f.readline() print(f'第二行:{content}') f.close() ``` 注意不同文件模式指针带来的问题 ```python # w+ 特点:会用新内容覆盖原内容,即使没有调用 write() 方法 f = open('test.txt', 'w+') print(f.read()) f.close() # a+ 特点:不会覆盖原内容,但是因为指针在结尾,无法读取数据 f = open('test1.txt', 'a+') print(f.read()) f.close() ``` `seek()` 作用:用来移动文件指针。语法如下: + 起始位置:0 文件开头 1 当前位置 2 文件结尾 ```plaintext 文件对象.seek(偏移量, 起始位置) ``` ```python ''' 目标: 1. r 改变指针位置:改变读取数据开始位置或把指针放到结尾 2. a 改变指针位置:做到可以读取出来数据 ''' f = open('test.txt', 'r+') # f.seek(2, 0) # 改变读取数据开始位置 f.seek(0, 2) # 指针放到结尾 print(f.read()) f.close() f2 = open('test1.txt', 'a+') f2.seek(0, 0) # 指针移动到开头 print(f2.read()) f2.close() ```