文件操作

| 1.文件的概念 |
| 就是操作系统暴露给用户操作硬盘的快捷方式 |
| |
| |
| 2.代码打开文件的两种方式 |
| 方式1: |
| f = open(文件路径,读写模式,encoding='utf8') |
| f.close() |
| 在python3下open函数可以通过encoding参数指定编码方式,而在2中不可以 |
| |
| |
| 方式2: |
| with open('a.txt','r', encoding='utf8') as f1: |
| with子代码块 |
| ps:with上下文管理好处在于子代码运行结束自动调用close方法关闭资源 |
| """ |
| open方法的第一个参数是文件路径 并且撬棍跟一些字母的组合会产生特殊的含义导致路径查找混乱 为了解决该问题可以在字符串的路径前面加字母r |
| D:\a\n\t |
| r'D:\a\n\t' |
| 以后涉及到路径的编写 推荐加上r |
| |
| with支持一次性打开多个文件 |
| with open() as f1,open() as f2,open() as f3: |
| 子代码 |
| """ |
| 使用with这种上下文环境的方式打开文件,在对文件操作完成后无需通过close()关闭文件,文件会自动关闭,而且安全系数更高。 |
文件读写模式
| 'r' 只读模式:只能读 不能编写 |
| |
| |
| with open(r'a.txt', 'r', encoding='uf8') as f: |
| print(f.read()) |
| |
| 'w' 只写模式:只能写不能看 |
| |
| |
| |
| |
| with open(r'a.txt', 'w', encoding='utf8') as f: |
| f.write('假期综合征 赶紧要调整\n') |
| f.write('假期综合征 赶紧要调整\n') |
| f.write('假期综合征 赶紧要调整\n') |
| '''强调:换行符需要自己添加 并且在后续数据读取比对的时候也一定要注意它的存在''' |
| |
| 'a' 只追加模式:在文件末尾添加数据 |
| |
| |
| |
| |
| with open(r'a.txt', 'a', encoding='utf8') as f: |
| f.write('寄') |
| """ |
| pass 用于填充空白 有些部分不知道怎么写的代码可以用pass |
| 只能补全语法不全的功能 本身没有任何含义 |
| """ |
文件操作模式
| t 文本模式 |
| 默认的模式 |
| 1.只能操作文本文件 |
| 2.读写都是以字符为单位 |
| 3.需要指定encoding参数 不知道则默认使用计算机默认编码 |
| |
| b 二进制模式(bytes模式) |
| 不是默认的模式 需要自己指定 |
| 1. 可以操作任意类型的文件 |
| 2. 读写都是以bytes为单位 |
| 3.不需要指定的encoding参数 因为它本身就是二进制模式了 不需要编码 |
| """二进制模式与文本模式针对文件路径是否存在的情况下 规律是一样的!!!""" |
文件的诸多操作方法
| 1.read() |
| |
| 并且当文件内容比较多的时候 该方法还可能会造成计算机内存溢出 |
| |
| 2.for循环 |
| 一行行读取内容,避免内存溢出现象 |
| 3.readline() |
| 一次只读一行内容 |
| 4.readlines() |
| 一次性读取所有内容 会按照行数组织成列表的一个个数据值 |
| 5.readable() |
| 判断文件是否具备读取能力 |
| |
| 6.wirte() |
| 写入数据 |
| 7.writeable() |
| 判断文件是否具备写数据的能力 |
| 8.writelines() |
| 接收一个列表 一次性将列表中所有的数据值写入 |
| 9.flush() |
| 将内存中文件数据立刻刷到硬盘 等价于ctrl + s |
文件内光标的移动
| with open(r'a.txt', 'rb') as f: |
| print(f.read()) |
| f.seek(0,0) |
| print(f.read()) |
| f.seek(0, 0) |
| print(f.read()) |
| |
| |
| |
| |
| seek(offset, whence) |
| offset是位移量 以字节为单位 |
| whence是模式 0 1 2 |
| 0是基于文件开头 |
| 文本和二进制模式都可以使用 |
| 1是基于当前位置 |
| 只有二进制模式可以使用 |
| 2是基于文件末尾 |
| 只有二进制模式可以使用 |
| |
- 文件内光标的移动实战演练
- 计算机硬盘存取数据的原理
- 文件内容修改
- 函数简介
- 函数的语法结构
- 函数的定义与调用
文件内光标移动案例(了解)
| import time |
| with open(r'a.txt', 'rb') as f: |
| f.seek(0, 2) |
| while True: |
| line = f.readline() |
| if len(line) == 0: |
| |
| time.sleep(0, 5) |
| else: |
| print(line.decode('uf8'), end='') |
计算机硬盘修改数据的原理(了解)
硬盘写数据可以看成再硬盘上刻字 一旦需要修改中间内容 则需要重新刻字
因为刻的字不可能再从中间分开
硬盘删除数据的原理
不是直接删除而是改变状态 等待后续数据的覆盖才会被真正的删除
文件内容的修改
| |
| |
| |
| |
| |
| 优点:不耗费硬盘 |
| 缺点:耗费内存 |
| |
| '''先在另外一个地方写入内容 然后将源文件删除 将新文件命名成源文件''' |
| import os |
| with open('a.txt', 'r', encoding='utf8') as read_f, \ |
| open('.a.txt.swap', 'w', encoding='utf-8') as write_f: |
| for line in read_f: |
| write_f.write(line.replace('tony', 'kevinSB')) |
| os.remove('a.txt') |
| os.rename('.a.txt.swap', 'a.txt') |
| 优点:节约内存 |
| 缺点:消耗硬盘 |
函数前戏
| name_list = ['jason', 'kevin', 'oscar', 'jerry'] |
| |
| '''突然len不准用了''' |
| |
| |
| |
| |
| '''统计列表内数据值个数的代码需要在很多地方使用''' |
| |
| """ |
| 循环 |
| 相同的代码在相同的位置反复执行 |
| 函数 |
| 相同的代码在不同的位置反复执行 |
| ps:相同的代码不是真正一模一样而是可以通过传入的数据不同而做出不同的改变 |
| """ |
| def my_len(): |
| count = 0 |
| for i in name_list: |
| count += 1 |
| print(count) |
| my_len() |
| """ |
| 函数相当于是工具(具有一定功能) |
| 不用函数 |
| 修理工需要修理器件要用锤子 原地打造 每次用完就扔掉 下次用继续原地打造 |
| 用函数 |
| 修理工提前准备好工具 什么时候想用就直接拿出来使用 |
| """ |
函数的语法结构
| def 函数名(参数): |
| '''函数注释''' |
| 函数体代码 |
| return 返回值 |
| 1.def |
| 定义函数的关键字 |
| 2.函数名 |
| 命名等同于变量名 |
| 3.参数 |
| 可有可无 主要是再使用函数的时候规定要不要外界传数据进来 |
| 4.函数注释 |
| 类似于工具说明书 |
| 5.函数代码体 |
| 是整个函数的核心 主要取决于程序员的编写 |
| 6.return |
| 使用函数之后返回给使用者的数据 可有可无 |
函数的定义与调用
| 1.函数再定义的阶段只检测语法 不执行 |
| def func(): |
| pass |
| 2.函数再调用阶段才会执行函数代码体 |
| func() |
| 3.函数必须先定义后使用 |
| 4.函数定义使用关键字def函数调用使用>>>:函数加括号 |
| 如果有参数则需要再括号内按照相应的规则传递参数 |
函数的分类
| 1.空函数 |
| 函数的代码体是空的 使用pass或者...补全 |
| 空函数主要用于项目前期的功能框架搭建 |
| def register(): |
| 2.无参函数 |
| 定义函数的时候括号内没有参数 |
| def index(): |
| print('from index function') |
| 3.有参函数 |
| 定义函数的括号内参数 调用函数的时候传参数 |
| def func(a): |
| print(a) |
函数的返回值
| 1.什么是返回值 |
| 调用函数之后返回给调用者的结果 |
| 2.如何获取返回值 |
| 变量名 赋值符号 函数的调用 |
| res = func() |
| 3.函数返回值的多种情况 |
| 3.1.函数代码体中没有return关键字 默认返回None |
| 3.2.函数代码有return 如果后面没有写任何东西还是返回None |
| 3.3.函数体代码有return 后面有什么写什么 |
| 3.4.函数体代码有return并且后面有多个数据值 则自动返回组成元组返回 |
| 3.5.函数代码体碰到return自动结束 |
函数的参数
| 形式参数 |
| 在函数定义阶段括号内填写的参数 简称'形参' |
| 实际参数 |
| 在函数调用阶段括号内填写的参数 简称'实参' |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| """ |
| 形参与实参的关系 |
| 形参类似于变量名 在函数定义阶段可以随便写 最好见名知意 |
| def register(name,pwd): |
| pass |
| |
| 实参类似于数据值 在函数调用阶段与形参临时绑定 函数运行结束立刻断开 |
| register('jason',123) 形参name与jason绑定 形参pwd与123绑定 |
| """ |
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| |
多层语法糖

| def outter1(func1): |
| print('加载了outter1') |
| def wrapper1(*args, **kwargs): |
| print('执行了wrapper1') |
| res1 = func1(*args, **kwargs) |
| return res1 |
| return wrapper1 |
| |
| def outter2(func2): |
| print('加载了outter2') |
| def wrapper2(*args, **kwargs): |
| print('执行了wrapper2') |
| res2 = func2(*args, **kwargs) |
| return res2 |
| return wrapper2 |
| |
| def outter3(func3): |
| print('加载了outter3') |
| def wrapper3(*args, **kwargs): |
| print('执行了wrapper3') |
| res3 = func3(*args, **kwargs) |
| return res3 |
| return wrapper3 |
| |
| |
| @outter1 |
| @outter2 |
| @outter3 |
| def index(): |
| print('from index') |
| """ |
| 多层语法糖 加载顺序由下往上 |
| 每次执行之后如果上面还有语法糖 则直接将返回值函数名传给上面的语法糖 |
| 如果上面没有语法糖 则变形 index = outter1(wrapper2) |
| """ |
有参装饰器
| |
| def outer(mode): |
| def login_auth(func_name): |
| def inner(*args, **kwargs): |
| res = func_name(*args, **kwargs) |
| return res |
| return inner |
| return login_auth |
| '''当装饰器中需要额外的参数时>>>:有参装饰器''' |
| |
| """ |
| 函数名加括号执行优先级最高 有参装饰器的情况 |
| 先看函数名加括号的执行 |
| 然后再是语法糖的操作 |
| """ |
| |
| def index(): |
| print('from index') |
| index() |
| |
| |
| def func(): |
| print('from func') |
| func() |
装饰器模板
| 最常用的无参装饰器 |
| def outer(func_name): |
| def inner(*args, **kwargs): |
| res = func_name(*args, **kwargs) |
| return res |
| return inner |
| @outer |
| def index(): |
| pass |
| |
| 不常用的有参装饰器 |
| def outer_plus(mode): |
| def outer(func_name): |
| def inner(*args, **kwargs): |
| res = func_name(*args, **kwargs) |
| return res |
| return inner |
| return outer |
| @outer_plus('MySQL') |
| def func(): |
| pass |
装饰器修复技术
| def index(): |
| """index函数 非常的牛""" |
| pass |
| help(index) |
| help(len) |
| from functools import wraps |
| def oute00+ |
| r(func_name): |
| @wraps(func_name) |
| def inner(*args, **kwargs): |
| """我是inner 我擅长让人蒙蔽""" |
| res = func_name(*args, **kwargs) |
| return res |
| return inner |
| |
| @outer |
| def func(): |
| """我是真正的func 我很强大 我很牛 我很聪明""" |
| pass |
| |
| |
| |
| |
| func() |
递归函数
| 1.函数的递归调用 |
| 函数直接或者间接的调用了函数自身 |
| 直接调用 |
| def index(): |
| print('from index') |
| index() |
| index() |
| 间接 |
| def index(): |
| print('from index') |
| func() |
| |
| def func(): |
| print('from func') |
| index() |
| |
| func() |
| '''最大递归深度:python解释器添加的安全措施''' |
| count = 0 |
| def index(): |
| global count |
| count += 1 |
| print(count) |
| index() |
| index() |
| '''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998''' |
| |
| 2.递归函数 |
| 1.直接或者间接调用自己 |
| 2.每次调用都必须比上一次简单 并且需要有一个明确的结束条件 |
| 递推:一层层往下 |
| 回溯:基于明确的结果一层层往上 |
| """ |
| get_age(5) = get_age(4) + 2 |
| get_age(4) = get_age(3) + 2 |
| get_age(3) = get_age(2) + 2 |
| get_age(2) = get_age(1) + 2 |
| get_age(1) = 18 |
| """ |
| def get_age(n): |
| if n == 1: |
| return 18 |
| return get_age(n-1) + 2 |
| res = get_age(5) |
| print(res) |
算法简介及二分法
算法(概念了解)
- 什么是算法
算法就是解决问题的有效方法 不是所有的算法都很高效 也有不合格的算法
- 算法应用场景
推荐算法(抖音视频推送 淘宝商品推送)
成像算法(AI相关)......
几乎涵盖了我们日常生活中的方方面面
- 算法的条件
输入性, 输出性,明确性, 有限性,有效性
- 时间复杂度
O(1)< O(login)<O(n)<O(n^2)<O(n!)
- 常见的大O运行时间(n一般为元素的个数):
- O(logn):对数时间,例如:二分查找
- O(n): 线性时间,简单查找
- O(nlogn): 快速排序
- O(n^2):选择排序
- O(n!):旅行商问题解决方案##
二分法
二分法是一个高效的算法 用于计算机的查找过程中
| 1.使用要求 |
| 二分法查找依赖的是顺序结构表,数组 |
| |
| 查找针对的是有序数据 所以只能用插入、删除操作不频繁,一次性多次查找的场景中 |
| 2.二分法的缺陷 |
| 针对开头结尾的数据 查找效率很低 |
| 常见算法的原理以及伪代码 |
| """数据量太小不适合二分查找,与直接遍历相比效率提升不明显。但有一个例外,就是数据之间的比较操作非常费时,比如数组中存储的都是组成长度超过100的字符串。 |
| """ |
| 3.一般要求找到某一个值或一个位置。 |
二分法代码示例
| l1 = [12, 21, 32, 43, 56, 76, 87, 98, 123, 321, 453, 565, 678, 754, 812, 987, 1001, 1232] |
| |
| |
| |
| def get_middle(l1, targer_num): |
| if len(l1) == 0: |
| print('没找到') |
| return |
| |
| middle_index = len(l1) // 2 |
| |
| if targer_num > l1[middle_index]: |
| |
| right_l1 = l1[middle_index+1:] |
| print(right_l1) |
| |
| return get_middle(right_l1, targer_num) |
| elif targer_num < l1[middle_index]: |
| |
| left_l1 = l1[:middle_index] |
| print(left_l1) |
| return get_middle(left_l1, targer_num) |
| else: |
| print('恭喜你找到了') |
| |
| |
| get_middle(l1, 754) |
三元表达式
| |
| name = 'jason' |
| if name == 'jason':print('老师') |
| else:print('学生') |
| |
| |
| res = '老师' if name == 'jason' else '学生' |
| print(res) |
| """ |
| 数据值1 if 条件 else 数据值2 |
| 条件成立则使用数据值1 条件不成立则使用数据值2 |
| |
| 当结果是二选一的情况下 使用三元表达式比较简便 |
| |
| 不推荐多个三元表达式嵌套 |
| """ |
各种生成式/表达式/推导式
| 给所有列表的人名的后面加上_NB的后缀 |
| |
| |
| |
| |
| |
| |
| new_list = [name + '_nb' for name in namelist] |
| print(new_list) |
| |
| |
| new_list = ['大佬' if name == 'wei' else '小赤佬' for name in namelist if name != 'jason'] |
| print(new_list) |
| |
-
列表生成式
先看for循环 每次for循环之后再看for关键字前面的操作
-
字典生成式

| s1 = 'hello world' |
| for i, j in enumerate(s1): |
| print(i, j) |
| d1 = {i: j for i, j in enumerate('hello')} |
| print(d1) |
-
集合生成式
| res = {i for i in 'hello'} |
| print(res) |
匿名函数
| 没有名字的函数 需要使用关键字lambda |
| 语法结构 |
| lambda 形参:返回值 |
| 使用场景 |
| lambda a,b:a+b |
| 匿名函数一般不单独使用 需要配合其他函数一起用 |
常见内置函数
| 1.map() 映射 |
| l1 = [1, 2, 3, 4, 5] |
| |
| |
| res = map(lambda x:x+1, l1) |
| print(list(res)) |
| |
| 2.max()\min() |
| l1 = [11, 22, 33, 44] |
| res = max(l1) |
| |
| d1 = { |
| 'zj': 100, |
| 'jason': 8888, |
| 'berk': 99999999, |
| 'oscar': 1 |
| } |
| def func(a): |
| return d1.get(a) |
| res = max(d1, key=func) |
| print(res) |
| 3. reduce |
| reduce 传多个值 返回一个值 |
| from functools import reduce |
| l1 = [11, 22, 33, 44, 55, 66, 77, 88] |
| res = reduce(lambda a, b:a * b, l1) |
| print(res) |
重要内置函数
| 1.zip() 拉链函数 |
| |
| l1 = [11, 22, 33, 44, 55] |
| l2 = ['jason', 'kevin', 'oscar', 'jerrry', 'tony'] |
| l3 = [1, 2, 3, 4, 5] |
| res = zip(l1, l2, l3) |
| |
| print(list(res)) |
| l1 = [11, 22, 33] |
| l2 = ['jason', 'kevin', 'oscar', 'jerry', 'tony'] |
| l3 = [1, 2, 3, 4] |
| res = zip(l1, l2, l3) |
| print(list(res)) |
| 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表 |
| |
| 2. filter() |
| |
| l1 = [11, 22, 33, 44, 55, 66, 77, 88] |
| res = filter(lambda x: x > 40, l1) |
| print(list(res)) |
| |
| |
| 筛选出序列中为奇数的元素: |
| def is_odd(n): |
| return n%2 == 1 |
| lst1 = filter(is_odd,[1,2,3,4,5,6,7,8,]) |
| |
| |
| 3.sorted |
| |
| l1 = [21, 12, 53, 64, 76, 32, 11, 22] |
| res = sorted(l1) |
| print(res) |
常见内置函数
| 1.abs() 绝对值 |
| print(abs(-100)) |
| |
| 2.all() 所有数据值对应的布尔值为True结果才是True 佛iu则返回False、 |
| print(all([0, 1, 2, 3])) |
| print(all([1, 2, 3])) |
| |
| 3.any() |
| |
| print(any([0, None, '', 1])) |
| print(any([0, None, ''])) |
| |
| 4.bin() oct() hex() int() |
| |
| 5.bytes() 转换成bytes类型 |
| w1 = '啊魏今天也很帅' |
| print(w1.encode('utf8')) |
| print(bytes(w1,'utf8')) |
| |
| |
| 6.callable() 判断名字是否可以加括号调用 |
| name = 'jason' |
| def index(): |
| print('from index') |
| print(callable(name)) |
| print(callable(index)) |
| |
| 7.chr() ord() 基于ASCII码表做数字与字母的转换 大写英文65-90 小写 97-122 |
| print(chr(65)) |
| print(ord('A')) |
| |
| 8.dir() 返回括号内对象能调用的名字 |
| print(dir('hello')) |
| |
| 9.divmod() 元组 第一个数据为整除数 第二个是余数 |
| res = divmod(100, 2) |
| print(res) |
| res = divmod(100, 3) |
| print(res) |
| """ |
| 总数据 每页展示的数据 总页码 |
| 100 10 10 |
| 99 10 10 |
| 101 10 11 |
| """ |
| page_num, more = divmod(9999, 20) |
| print(divmod(99, 10)) |
| if more: |
| page_num += 1 |
| print('总页码为', page_num) |
| |
| 10. enumerate() |
| |
| list = ['python', 'java', 'c'] |
| |
| for index,key in enumerate(list): |
| print(index,key) |
| 0 python |
| 1 java |
| 2 c |
| |
| 11.eval() exec() 能够识别字符串中的python并执行 |
| s1 = 'print("哈哈哈")' |
| eval(s1) |
| exec(s1) |
| s2 = 'for i in range(100):print(i)' |
| eval(s2) |
| exec(s2) |
| |
| 12.hash() 哈希加密 |
| print(hash('jason')) |
| |
| 13. id() input() isinstance() |
| |
| input() 提示用户输入信息 实现人机交互 |
| isinstance() : |
| |
| |
| 14.map() max() min() |
| |
| 15.open() |
| 函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。 |
| |
| 16.pow() 幂指数(次方) |
| print(pow(2, 2)) |
| print(pow(2, 3)) |
| print(pow(2, 4)) |
| |
| 17.range() 范围 |
| 18.round() 四舍五入\但是98.5 5不会进1 |
| print(round(98.3)) |
| print(round(98.6)) |
| |
| 19.sum() |
| print(sum([11, 22, 33, 44, 55, 66])) |
| 20.zip() |
可迭代对象
| 1.可迭代对象 |
| 对象内置有__iter__方法的称为可迭代对象 |
| """ |
| 1.内置方法 通过点的方式能够调用的方法 |
| 2.__iter__ 双下iter方法 |
| """ |
| 2. 可迭代对象的范围 |
| 不是可迭代对象 |
| int float bool 函数对象 |
| 是可迭代对象 |
| str list dict tuple set 文件对象 |
| """ |
| 可以对list、tuple、dict、set、str等类型的数据使用for...in...的循环语法从其中依次拿到数据进行使用,我们把这样的过程称为遍历,也叫迭代。 |
| """ |
| 3. 可迭代的含义 |
| """ |
| 迭代:更新换代(每次更新都必须依赖上一次的结果) |
| eg:手机app更新 |
| """ |
| 可迭代在python中可以理解为是否支持for循环 |
迭代器对象
| 1.迭代器对象 |
| 是由可迭代器对象调用__inter__方法产生的 迭代器对象判断的本质是看是内置有__inter__和__next__ |
| 2.迭代器对象的作用 |
| 提供了一种不依赖于索引取值的方式 |
| 正因为有迭代器的存在 字典集合才可以被for循环 |
| 3. 迭代器对象实操 |
| s1 = 'hello' |
| res = s1.__iter__() |
| print(res.__next__()) |
| 一旦__next__取不到值 会直接报错 |
| 4.注意事项 |
| 可迭代对象调用__iter__会成为迭代器对象 |
| 迭代器对象如果还调用__iter__不会有任何变化 还是迭代器对象本身 |
for循环本质
| for 变量名 in 可迭代对象: |
| 循环体代码 |
| """ |
| 1.先将in后面的数据调用__iter__转变成迭代器对象 |
| 2.依次让迭代器对象调用__next__取值 |
| 3.一旦__next__取不到值报错 for循环会自动捕获并处理 |
| """ |
异常捕获/处理
| 1.异常 |
| 异常就是代码运行报错 行业俗语叫bug |
| 代码运行中一旦遇到异常会直接结束整个程序的运行 我们在编写代码的过程中药尽可能避免 |
| 2.异常分类 |
| 语法错误 |
| 不允许出现 一旦出现立刻改正 否则提桶跑路 |
| 逻辑错误 |
| 允许出现的 因为它一眼发现不了 代码运行之后才可能会出现 |
| 3.异常结构 |
| 错误位置 |
| 错误类型 |
| 错误详情 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本