周末回顾 10.8 - 10.14
周末回顾
一、文件
1.什么是文件
| 文件:文件是操作系统提供给应用程序来操作硬盘的虚拟概念。 |
| 数据都保存在硬盘中,应用程序想要对其进行操作,在操作系统中就出现了文件的概念。从而应程序能够通过操作系统去对硬盘进行调用。 |
2.文件操作的流程
| 文件操作的流程:打开文件>>>调用文件>>>>关闭文件 |
| 1.打开文件 |
| 关键字 open(要打开的文件的路径,操作模式,encoding编码方法) |
| open可以由应用程序通过操作系统打开硬盘中对应的文件路径,按照指定模式操作,并返回一个文件对象 |
| |
| |
| 2.调用文件 |
| f.read 读文件 |
| f.write 写文件 |
| 3.关闭文件 |
| f.cloes 关闭文件 |
| 1.资源回收 |
| 资源分为两部分 1 应用程序接收的变量名 f 2 操作系统打开的文件 |
| |
| 资源回收就是回收这两部, |
| 一个用 1 f.close来回收系统调用的f, |
| 一个用 2 del f 回收应用文件级别的文件 |
| |
| 而 del f 要在 f.close 之后,否则无法回收,所以有了with上下文管理方法来操作文件 |
| |
| 2.with上下文管理方法 |
| with方法不需要 close方法和 del f,就可以自动帮我们关闭文件的调用 |
| |
| |
| with open(要打开的文件的路径,操作模式,指定编码方法) as 变量名f: |
| with体代码 |
| |
3.文件的操作模式
| 1.r模式,只读模式只能读不能写 |
| |
| 2.w模式,只能写不能读,每次用w模式打开文件都会清空文件中的内容,重新写入 |
| |
| 3.a模式,可读可写,写的内容只在尾部追加 |
| |
| 1.t模式文本模式 |
| 只能操作文本文件,并对文本文件进行读写操作,而且要指定字符编码模式 |
| 2.b模式二进制模式 |
| 可以操作任意类型的文件,并且必须不能指定字符编码模式 |
3.操作文件的方法
| |
| 1.读操作 |
| 1) f.read() 一次性读取文件中所有的内容 |
| 2) f.readline() 按行读取文件中的内容,结束之后光标跳转至第二行开头 |
| 3) f.readlines() 一行行的读取文件中的全部内容,结束之后光标跳转至文件末尾 |
| |
| |
| 2.写操作 |
| 1) f.write() |
| 对t文本模式写入数据的时候,可以不指定字符编码模式 |
| 对b二进制模式的是写入数据,必须要指定字符编码模式 |
| |
| |
| |
| 2) f.writelines() |
| 对t文本模式,是接收一个列表,一次性写入全部内容 |
| 对b二进制模式,需要先将写入的内容用 bytes()转换为字节串 |
| |
| 1. f.readable() |
| 2. f.writeable() |
| 3. f.closed() |
| 4. f.encoding() |
| 5. f.flush() |
4.文件内光标的移动
| 文件内有指针的概念,用来操作文件内的读写。 |
| 1. seek(offset,whence)方法 |
| offset:指针的移动字节 |
| whence:操作的模式 0模式是默认模式,从文件开头操作 |
| 1模式,从当前位置曹祖 |
| 2模式,从文件末尾操作 |
| |
| 2. tell()方法 告诉我们指针的位置 |
5.文件的修改
| 硬盘修改数据不是直接修改或者增减,而是覆盖了旧的数据 |
| 1.覆盖写 |
| |
| with open(r'a.txt','r',encoding='utf8') as f: |
| data = f.read() |
| with open(r'a.txt', 'w', encoding='utf8') as f1: |
| f1.write(data.replace('jason', 'tony')) |
| |
| 2.换地方写 |
| |
| import os |
| with open(r'a.txt','rt',encoding='utf8') as read_f,\ open(f'a.txt.swap','w',encoding='utf8') as write_f: |
| for line in read_f: |
| write_f.write(line.replace('tony', 'kevin')) |
| |
| |
| os.remove('a.txt') |
| os.rename('.a.txt.swap','a.txt') |
二、函数
1.什么是函数
| 函数是一种存放代码体的容器,它具备一定处理数据的功能 |
| |
| 1.定义函数 |
| 定义函数,相当于将函数名绑定函数体代码,当我们调用函数时,相当于通过函数名调用此段函数体代码 |
| 2.函数的语法 |
| def 函数名(参数): |
| '''函数注释''' |
| 函数体代码 |
| return 返回值 |
| ''' |
| def 是定义函数的关键字 函数名应该见名知意,需要表达函数的功能 |
| 参数是我们可以通过其向函数内部传数据 |
| 函数注释是帮助我们来对函数功能进行描述的 |
| 函数体代码是函数功能实现的主要核心诶人 |
| return 返回值是返回调用者的数据值 |
| ''' |
| 1.空函数 函数体代码为 pass 或者 ... |
| |
| 2.有参函数 |
| 参数是向函数体代码传递数据的中介 |
| 3.无参函数 |
| 没有参数的函数 |
2.调用函数与函数的返回值
| 1.定义函数时只检测语法 |
| 2.调用函数才执行函数体代码 |
| 调用函数 直接用函数名加括号 |
| index() |
| 1.什么是函数的返回值 如何获取 |
| 函数的返回值是函数返回给调用者的结果 用 return来定义 |
| 用一个变量名来接收函数调用的返回值 |
| 变量名 = 函数名() |
| |
| 2.返回值的情况 |
| 没有 return 返回 None |
| 拥有 return + 没有东西 返回 None |
| + something 返回 something |
| + 单个数据 返回 单个数据 |
| + 多个数 返回 包含多个数据的元组 |
| |
3.函数的参数
| 1.形式参数'形参' |
| 定义阶段括号内的参数 |
| 2.实际参数'实参' |
| 调用阶段括号内的参数 |
| 1.位置新参,在定义阶段 从左到右的顺序定义的参数叫做位置形参,位置形参必须要被传值 |
| 2.位置实参,在调用阶段,从左到右的顺序调用的参数叫做位置实参,位置实参会被按照顺序传给位置形参 |
| |
| def func1(a, b): |
| print(a) |
| |
| func1(1, 2) |
| key = value 这种形式的传参,叫做关键字参数,关键字参数可以打破位置传参的顺序,将想要传递的数据值直接指定给某个位置形参 |
| |
| |
| 1.关键字传参一定要在位置参传参后面,在位置传参之前不符合参数的排列顺序 会报错 |
| 2.关键字传参只能给一个位置形参传递一个数据值,多了会报错 |
| 3.关键字传参可以传数据值,也可以穿变量名 |
| |
| |
| name = 'duoduo' |
| def func1(a, b,c): |
| print(a,b,c) |
| |
| func1(2, b=1, c = name) |
| 默认参数的本质:关键字形参 |
| |
| name = 'jason' |
| def func1(a, b, c='duoduo'): |
| print(a, b, c) |
| |
| 1 实参和默认形参一致时不用传参 |
| func1(2, b=1) |
| |
| 2 实参和默认形参不一致时 用关键字传参 |
| |
| func1(2, b=1, c='lulu') |
| func1(2, b=1, c=name) |
| 在定义阶段,用带*形参 来接收多余的位置实参,用带**形参 来接收多余的关键字参数 |
| 1. *args 接收多余的位置实参 |
| 会自动接收多余的位置实参,并将其以元组的形式保存起来 |
| |
| 2.**kwargs 接收多余的关键字参数,并将其以字典中键值对的形式保存起来 |
| |
| def func1(a, *b,**c): |
| print(a, b, c) |
| |
| func1() |
| func1(1) |
| func1(2, b=1) |
| func1(2, b=1, c='lulu') |
| 在函数调用阶段,用* 和** 将数据集中的数据打散 |
| 1.*args 将数据集中的元素,按照位置顺序传递给函数体代码 |
| |
| 2.**kwargs 将字典打散成关键字参数,并按照顺序将其传递给函数体代码 |
| |
| name_l = ['jason', 'duo', 'qiu'] |
| name_d = {'name': 'duo', 'age': 12, 'hobby': 'lol'} |
| |
| |
| def func1(a, b, c): |
| print(a, b, c) |
| |
| |
| def func2(name,age,hobby): |
| print(name,age,hobby) |
| |
| func1(*name_l) |
| func2(**name_d) |
参数的顺序是:
位置参数、默认参数(关键字形参)、*args、命名关键字参数、**kwargs
4.函数名的多种用法
| 函数名可以当作绑定了函数体代码的变量名,赋值给别的变量名之后,别的变量名也可以调用该函数体代码 |
| |
| def func1(): |
| print('咖啡苦不如命苦') |
| index = func1 |
| index() |
| 可以当作参数传值进去 |
| |
| |
| def func1(): |
| print('咖啡苦不如命苦') |
| def func2(): |
| print('天天开心') |
| |
| def index(a): |
| a() |
| |
| |
| index(func1) |
| index(func2) |
| 函数名还可以为其他函数的返回值,当有变量名接收的时候,调用其变量名则可以调用该函数 |
| 1)两个独立的函数 |
| |
| def func1(): |
| print('咖啡苦不如命苦') |
| |
| def func2(): |
| print('天天开心') |
| return func1 |
| |
| func2() |
| res = func2() |
| res() |
| |
| ——————————运行结果—————————— |
| 天天开心 |
| 天天开心 |
| 咖啡苦不如命苦 |
| |
| 2)嵌套的函数 |
| |
| def func1(): |
| print('咖啡苦不如命苦') |
| def func2(): |
| print('天天开心') |
| return func2 |
| |
| func1() |
| res = func1() |
| res() |
| ——————————运行结果—————————— |
| 咖啡苦不如命苦 |
| 咖啡苦不如命苦 |
| 天天开心 |
| 可以作为 元组、字典、列表、集合的元素,通过索引它们的值加括号调用该函数 |
| |
| def func1(): |
| print('咖啡苦不如命苦') |
| |
| d1 = {'name':func1} |
| d1.get('name')() |
5.闭包函数
| 闭包函数的要求 |
| 1 该函数定义在另一个函数内部 |
| 2 用到了外部函数的局部名称空间中变量 |
| |
| |
| def outer(): |
| name = 'duo' |
| def inner(): |
| print(name) |
| 传参的方式 1:在定义函数时直接添加形参 |
| 传参的方式 2:闭包函数 |
| |
| def outer(name): |
| def inner(): |
| print(name) |
| 可以将实参的返回值赋值给变量名,然后可以重复调用 |
| |
| def outer(name): |
| def inner(): |
| print(name)def outer(name): |
| def inner(): |
| print(name) |
| return inner |
| res = outer('duo') |
| res() |
| res() |
| res = outer('kuku') |
| res() |
| res() |
三、名称空间
1.名称空间的分类
| 名称空间:就是在内存内申请一块地方保存变量名和数据值的绑定关系,后续可以通过该变量名来访问数据值,保存变量名的地方叫做名称空间 |
| |
| 1.内置名称空间:python解释器中内置的名称的空间 |
| |
| 2.全局名称空间:运行python中文件产生的空间 |
| |
| 3.局部名称空间:运行函数体代码或者类体代码时产生的空间 |
| |
2.名称空间存活周期及作用域
| 1.内置名称空间: |
| python解释器启动则创建,关闭则销毁,解释器级别的全局有效 |
| 2.全局名称空间: |
| py文件创建执行后,关闭文件则销毁,文件全局有效 |
| 3.局部名称空间: |
| 函数体代码运行则创建,运行结束则销毁,在函数体代码内有效 |
3.名字的查找顺序
| |
| |
| 1 名字空间的加载顺序: 内置> 全局> 局部 |
| |
| 2 名字空间的查找顺序: 局部> 全局> 内置 |
四、global 和 nonlocal
| 1.global 在局部名称空间中,使用 global关键字可以修改全局名称空间中该变量名绑定的数据(整型 字典 元组) |
| |
| 2.nonlocal 在内层名称空间中修改层名称空间中的变量名 |
| |
五、装饰器
1.什么是装饰器
| 1.装饰器的功能 |
| 可以在不改变被装饰对象的代码和调用方式的情况下,为被装饰对象添加新的功能 |
| 2.装饰器本质: 是函数参数、闭包函数、函数名多种用法、空间名称组合在一起的产物 |
2.装饰器模版
| 1 |
| def outer(func): |
| def inner(*args, **kwargs): |
| |
| res = func(*args, **kwargs) |
| |
| return res |
| |
| return inner |
| |
| 2 |
| def wrapper(condition): |
| def outer(func): |
| def inner(*args,**kwargs): |
| |
| res = func(*args,**kwargs) |
| |
| return res |
| return inner |
| return outer |
3.装饰器语法糖
| 1.语法糖:用@符号 + 装饰器名 调用该装饰器 |
| 2.语法糖作用: 然后把紧贴它下面的函数名当作参数传入装饰器中,然后将返回的值赋值给原函数名 |
| |
| |
| def func1(): |
| print('这里是func1') |
| |
| |
| |
| def outer(func): |
| def inner(*args, **kwargs): |
| |
| res = func(*args, **kwargs) |
| |
| return res |
| |
| return inner |
| |
| 1)使用装饰器的方法 1:赋值给原函数名 |
| func1 = outer(func1) |
| func1() |
| |
| 2)使用装饰器的方法 2: 使用语法糖,在被装饰的函数前 |
| @outer |
| def func2(): |
| print('这里是func2') |
| func2() |
4.多层语法糖
| 多层语法糖的装饰顺序,从下往上,遇到最后一个语法糖才会将与原函数名相同的变量名传给装饰器调用 |
| |
| |
| |
| |
| |
| def outer1(func): |
| print('outer1') |
| |
| def wrapper1(*args, **kwargs): |
| print('wrapper1') |
| res = func(*args, **kwargs) |
| return res |
| |
| return wrapper1 |
| |
| |
| def outer2(func): |
| print('outer2') |
| |
| def wrapper2(*args, **kwargs): |
| print('wrapper2') |
| res = func(*args, **kwargs) |
| return res |
| |
| return wrapper2 |
| |
| |
| def outer3(func): |
| print('outer3') |
| |
| def wrapper3(*args, **kwargs): |
| print('wrapper3') |
| res = func(*args, **kwargs) |
| return res |
| |
| return wrapper3 |
| |
| |
| @outer1 |
| @outer2 |
| @outer3 |
| def index(): |
| print('index') |
| |
| |
| index() |
六、函数的递归调用
1.什么是函数的递归调用
| |
| |
| 函数的递归调用分为直接调用和间接调用 |
| 1.直接调用:函数在定义阶段中就调用了自己 |
| 2.间接调用:函数在定义阶段中调用了别的函数 |
| 3.最大递归深度: 1000次,在python中 递归调用是有次数限制的为1000,超过1000次会报错 |
2.递归函数的定义
| 递归定义: 1)直接或者间接调用了自己本身 2)每次调用都必须比上次简单,而且有明确的结束条件的函数 |
3.递归函数的特点
| 1.直接或者间接的调用了自己,但是递归的效率不高 |
| 2.相邻两次的递归之间关系紧密,且上一次递归要为下一次递归作准备 |
| 3.每次进入更深一层的递归时,问题本身的复杂程度或者规模会减少 |
| 4.必须有一个明确的结束条件 |
七、算法简介及二分法
1.算法
| 算法就是针对专门问题的解决方法,算法可以被优化,但是对一个问题来说没有最完美的算法 |
2.二分法
| 就是将一段有序数列,不断的一分为二,然后拿中间的值去比较目标数据,然后判断中间值左右两边的小数列哪个更接近目标数据,再去一分为二,直到得到目标数据,或者数列被分割结束。 |
| |
| |
| l1 = [11, 33, 44, 53, 65, 76, 88, 99, 112, 232, 343] |
| |
| |
| def get_num(l, target_num): |
| if len(l) == 0: |
| print('结束') |
| middle_index = len(l) // 2 |
| if target_num > l[middle_index]: |
| right_l = l[middle_index + 1:] |
| print(right_l) |
| return get_num(right_l, target_num) |
| elif target_num < l[middle_index]: |
| left_l = l[:middle_index] |
| print(left_l) |
| return get_num(left_l, target_num) |
| else: |
| print('find it') |
| |
| |
| get_num(l1, 99) |
八、生成式
| 生成式可以对数据集进行相同的操作,从而简化代码 |
| |
| 1.列表生成式 |
| l = [变量名 + 想进行的操作 for 元素 in 原列表 if 变量名满足的条件] |
| |
| |
| l1 = [11, 33, 44, 53, 65, 76, 88, 99, 112, 232, 343] |
| |
| l2 = [number + 1 for number in l1 if number > 70] |
| print(l2) |
| |
| 2.字典生成式 |
| |
| d2 = {i: j for i, j in enumerate('hello', 22)} |
| print(d2) |
| |
| d1 = [(11,22)] |
| d2 = {i: j for i, j in d1} |
| print(d2) |
| |
| 3.集合生成式 |
| s1 = {i for i in 数据集} |
| 生成一个集合,元素来源于数据集中 |
| |
| s1 = {i for i in 'hello'} |
| d1 = [11,22,(111,222)] |
| s1 = {i for i in d1} |
| print(s1) |
九、匿名函数
| 1.语法结构 |
| lambda 形参:返回值 |
| 2.特点:匿名函数需要配合其他函数一起使用,且匿名函数不用写 return,其参数可以有多个 |
十、重要的内置函数
函数名 |
功能 |
map 映射 |
根据提供的函数对指定数据集做映射 |
max\min |
返回最大\最小值 |
ruduce |
传多个值,返回一个值 |
isinstance |
判断某个数据是否是某个数据类型 |
zip 组合 |
将列表中位置顺序相同的一起结合成元组 |
filter 过滤 |
过滤数据集中的不符合某条件的数据 |
sorted |
数据集中的数据, 按照大小升序排列 |
十一、常见的内置函数
函数名 |
功能 |
abs()绝对值 |
取数据的绝对值 |
all() |
所有数据值对应的布尔值为 True结果才是 True,否则返回 False |
any() |
所有数据值对应的布尔值有一个为 True结果才是 True,否则返回 False |
bin二进制 oct十进制 hex十六进制 int整数 |
将其他进制数转为该进制数 |
bytes() 编码 |
返回一个新的“bytes”对象,它是0<=x<256范围内的不可变整数序列。 |
callable() 调用 |
判断某一个名字是否可以加括号()调用 |
chr() |
chr(ASCII码编号) 返回对应字母 |
ord() |
ord(对应字母) 返回ASCII码编号 |
dir() |
返回括号内对象里面能调用的 名字 |
divmod() |
返回元组第一个数据为整除数 第二个是余数 |
enmerate(i,起始值) 枚举 |
将i中的元素遍历,并按照顺序和递增的起始值 一一组队输出成一个个元组 |
eval() |
eval() 只能识别简单的python代码,具有逻辑性的都不行 |
exec() |
可以识别具有一定逻辑性的python代码 |
id |
返回内存地址 |
input |
获取输入 |
instance |
判断数据类型 |
hash() |
哈希加密 |
open |
由应用程序向操作系统发起系统调用 open(...),操作系统打开该文件,对应一块硬盘空间,并且返回一个文件对象 |
pow(x, y[, z]) |
函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于 pow(x,y) %z |
range() |
生成一系列连续整数 |
round() 五舍六入 |
把浮点型的数据保留整数 |
sum() |
将数据集中的数据求和 |
十二、可迭代对象
1.可迭代对象的定义
| 定义:数据对象内置有 __iter__方法,可称为可迭代对象 |
2.可迭代对象的范围
| 1.可迭代对象范围(支持for循环) |
| str list dict tuple set 文件 |
| 2.不可迭代对象 |
| int float bool 函数对象 |
3.可迭代的含义
a ```python
十三、迭代器对象
1.迭代器对象
| 支持迭代的对象,调用了__iter__方法之后就变成了迭代器对象,其内置了__next__方法 |
2.迭代器对象
3.迭代器对象实操
| |
| s1 = 'hello' |
| res = s1.__iter__() |
| print(res.__next__()) |
| 一旦__next__取不到值就会报错 |
4.注意事项
| 可迭代对象调用__iter__会变成迭代器对象,迭代器对象如果还调用可迭代对象调用__iter__还是迭代器对象没有变化 |
| |
| 简写: |
| iter() |
| next() |
十四、for循环的本质
| for 变量名 in 可迭代对象: |
| 循环体代码 |
| 本质: |
| 1 先将in后面的数据调用__iter__方法转换为迭代器对象 |
| 2 依次用迭代器对象调用__next__取值 |
| 3 一旦__next__取不到值报错,for循环会自动捕获并处理 |
十五、异常捕获与异常处理
| 1.异常 |
| 异常就是代码运行报错,也叫bug |
| |
| 2.异常类型 |
| 1)语法错误 |
| 不允许出现错误 |
| 2)逻辑错误 |
| 允许出现,在代码运行之后才可能会出现 |
| |
| 3.异常报错显示区的内容 |
| 部分 1)异常出现的位置 |
| 部分 2)异常出现的类型:部分 3)异常的类型 |
代码实战篇
| 1.编写⽤户识别程序 |
| 要求: |
| 可循环根据⽤户输⼊的姓名不同输出不同的身份信息 |
| 添加程序结束功能(如⽤户输⼊字⺟q直接结束识别程序) |
| |
| user_info = {'jason': '扫地僧', 'tony': '洗碗⼯', 'kevin': '服务员', 'jack': '配菜员'} |
| |
| while True: |
| username = input('请输入您的名字(输入q退出验证):').strip() |
| if username == 'q': |
| break |
| elif username in user_info: |
| user_info_job = user_info.get(username) |
| print(f'您的职务为:{user_info_job}') |
| continue |
| else: |
| print('您的职务未识别') |
| |
| |
| 2.利⽤for循环及range⽅法⾃动⽣成链家⼆⼿房多⻚数据⽹址(⼗条以 |
| 上即可) |
| 初始⽹址:https://sh.lianjia.com/ershoufang/ |
| |
| |
| |
| |
| |
| """ |
| range(a,b,c)函数是生成从a到 b-1 的数据值,c是这个数列的等差值,不写c默认为1 |
| 在python 2.x中,使用range()函数,会将这些数据全部生成,而xrange()则会将这些数据 |
| 保存在某处,当我们需要时才会调用 |
| 而python 3.x中,已经删除了原来的range()函数,而新版本中的range()则是功能和xrange()一致 |
| """ |
| |
| |
| |
| def url_page(a, b, mode=1): |
| for i in range(a, b, mode): |
| print('https://sh.lianjia.com/ershoufang/pg%s/' % i) |
| |
| |
| url_page(1, 20) |
| |
| |
| 3.编写⽤户登录程序 |
| 温馨提示: |
| ⽤户名与密码来源于字符串source_data = 'jason|123' |
| 想办法从中拆分出⽤户名和密码⽤于后续账户信息⽐对 |
| 普通要求: |
| 1.验证失败情况下可⼀直循环验证 成功则直接退出 |
| 拔⾼练习: |
| 1.只允许三次失败机会 |
| 2.登录成功后进⼊内层循环,⽤户输⼊任何指令利⽤格式化输出 |
| 打印正在执⾏该⽤户指令即可,直到⽤户输⼊字⺟q退出内层循环 |
| |
| |
| source_data = 'jason|123' |
| |
| count = 1 |
| |
| while True: |
| |
| |
| if count > 3: |
| print('尝试三次机会已用完') |
| break |
| |
| username = input('请输入用户名:').strip() |
| password = input('请输入密码:').strip() |
| |
| real_name, real_pwd = source_data.split('|') |
| |
| if username == real_name and password == real_pwd: |
| print('登陆成功') |
| |
| while True: |
| user_func = input('请输入您想要输入的指令(输入q结束):') |
| if user_func == 'q': |
| break |
| else: |
| print(f'{user_func}正在运行') |
| else: |
| |
| count += 1 |
| print('您的用户名或者密码错误') |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY