目录
文件操作
1.文件的概念
就是操作系统暴露给用户操作硬盘的快捷方式
# 双击一个文件 其实是从硬盘将数据加载到内存
# ctrl+s保存文件 其实是将内存中的数据刷到硬盘保存
2.代码打开文件的两种方式
方式1:
f = open(文件路径,读写模式,encoding='utf8')
f.close()
在python3下open函数可以通过encoding参数指定编码方式,而在2中不可以
# 1、未指定文件编码格式,如果文件编码格式与当前默认的编码格式不一致,那么文件内容的读写将出现错误。
# 2、如果读写文件有错误,会导致文件无法正确关闭。因为哪怕在后面有 f.close()
方式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' 只读模式:只能读 不能编写
# 1.文件路径不存在:会直接报错
# 2.文件路径存在:正常读取文件内容
with open(r'a.txt', 'r', encoding='uf8') as f:
print(f.read())
'w' 只写模式:只能写不能看
# 1.文件路径不存在:自动创建
# with open(r'b.txt', 'w', encoding='utf8') as f:
# pass
# 2.文件路径存在:先清空文件内容 之后再写入
with open(r'a.txt', 'w', encoding='utf8') as f:
f.write('假期综合征 赶紧要调整\n')
f.write('假期综合征 赶紧要调整\n')
f.write('假期综合征 赶紧要调整\n')
'''强调:换行符需要自己添加 并且在后续数据读取比对的时候也一定要注意它的存在'''
'a' 只追加模式:在文件末尾添加数据
# 1.文件路径不存在:自动创建
# with open(r'c.txt', 'a', encoding='utf8') as f:
# pass
# 2.文件路径存在:自动在末尾等待追加内容
with open(r'a.txt', 'a', encoding='utf8') as f:
f.write('寄')
"""
pass 用于填充空白 有些部分不知道怎么写的代码可以用pass
只能补全语法不全的功能 本身没有任何含义
"""
文件操作模式
t 文本模式
默认的模式 # r w a其实全称是 rt wt at
1.只能操作文本文件
2.读写都是以字符为单位
3.需要指定encoding参数 不知道则默认使用计算机默认编码
b 二进制模式(bytes模式)
不是默认的模式 需要自己指定 # rb wb ab
1. 可以操作任意类型的文件
2. 读写都是以bytes为单位
3.不需要指定的encoding参数 因为它本身就是二进制模式了 不需要编码
"""二进制模式与文本模式针对文件路径是否存在的情况下 规律是一样的!!!"""
文件的诸多操作方法
1.read()
# 一次性读取所有内容 并且光标停留在尾部 继续读取则没有内容
并且当文件内容比较多的时候 该方法还可能会造成计算机内存溢出
# 括号内还可以填写数字 在文本模式下 表示读取几个字符
2.for循环
一行行读取内容,避免内存溢出现象
3.readline()
一次只读一行内容
4.readlines()
一次性读取所有内容 会按照行数组织成列表的一个个数据值
5.readable()
判断文件是否具备读取能力
# readable() 如果文件可读, 该方法返回True,否则返回False
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())
# print(f.read(2).decode('utf8')) 中文一个字 代码3个字节
# f.seek(-1, 2) 光标在末尾 -1 偏移数 向左移动1格
# print(f.tell()) # 返回光标距离文件开头产生的字节数
seek(offset, whence)
offset是位移量 以字节为单位
whence是模式 0 1 2
0是基于文件开头
文本和二进制模式都可以使用
1是基于当前位置
只有二进制模式可以使用
2是基于文件末尾
只有二进制模式可以使用
# print(f.read(3).decode('utf8')) 中文一个字 代码3个字节
- 文件内光标的移动实战演练
- 计算机硬盘存取数据的原理
- 文件内容修改
- 函数简介
- 函数的语法结构
- 函数的定义与调用
文件内光标移动案例(了解)
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='')
计算机硬盘修改数据的原理(了解)
硬盘写数据可以看成再硬盘上刻字 一旦需要修改中间内容 则需要重新刻字
因为刻的字不可能再从中间分开
硬盘删除数据的原理
不是直接删除而是改变状态 等待后续数据的覆盖才会被真正的删除
文件内容的修改
# 修改文件内容的方式1:覆盖写
# with open(r'a.txt', 'r', encoding='uf8') 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('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') # 删除a.txt
os.rename('.a.txt.swap', 'a.txt') # 重命名文件
优点:节约内存
缺点:消耗硬盘
函数前戏
name_list = ['jason', 'kevin', 'oscar', 'jerry']
# print(len(name_list))
'''突然len不准用了'''
# count = 0
# for i in name_list:
# count += 1
# print(count)
'''统计列表内数据值个数的代码需要在很多地方使用'''
# 相同的代码需要在不同的位置反复执行
"""
循环
相同的代码在相同的位置反复执行
函数
相同的代码在不同的位置反复执行
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() # 先执行func函数 然后将返回值赋值给变量res
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 # index = outter1(wrapper2) 只会在最后一个语法糖变形
@outter2 # outter2(wrapper3)>>>>:返回值是wrapper2
@outter3 # outter3(真正的index函数名)>>>:返回值是wrapper3
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
'''当装饰器中需要额外的参数时>>>:有参装饰器'''
"""
函数名加括号执行优先级最高 有参装饰器的情况
先看函数名加括号的执行
然后再是语法糖的操作
"""
# @outer('1')
def index():
print('from index')
index()
# @outer('2')
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
# help(func)
# print(func)
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 = []
# for name in namelist:
# data = f'{name}_nb'
# new_list.append(data)
# print(new_list)
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循环之后再看for关键字前面的操作
-
字典生成式
s1 = 'hello world' for i, j in enumerate(s1): # start= 代表从哪里开始 print(i, j) d1 = {i: j for i, j in enumerate('hello')} print(d1) # {0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o'}
-
集合生成式
res = {i for i in 'hello'} print(res) # {'l', 'e', 'h', 'o'}
匿名函数
没有名字的函数 需要使用关键字lambda
语法结构
lambda 形参:返回值
使用场景
lambda a,b:a+b
匿名函数一般不单独使用 需要配合其他函数一起用
常见内置函数
1.map() 映射
l1 = [1, 2, 3, 4, 5]
# def func(a):
# return a + 1
res = map(lambda x:x+1, l1)
print(list(res)) # [2, 3, 4, 5, 6]
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() 拉链函数
# zip 将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
l1 = [11, 22, 33, 44, 55]
l2 = ['jason', 'kevin', 'oscar', 'jerrry', 'tony']
l3 = [1, 2, 3, 4, 5]
res = zip(l1, l2, l3)
# [(11, 'jason', 1), (22, 'kevin', 2), (33, 'oscar', 3), (44, 'jerrry', 4), (55, 'tony', 5)]
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)) # [(11, 'jason', 1), (22, 'kevin', 2), (33, 'oscar', 3)]
如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表
2. filter()
# filter()函数用于过滤序列,过滤掉不符合条件的元素,返回符合条件的元素组成新列表。
l1 = [11, 22, 33, 44, 55, 66, 77, 88]
res = filter(lambda x: x > 40, l1)
print(list(res))
# [44, 55, 66, 77, 88]
筛选出序列中为奇数的元素:
def is_odd(n):
return n%2 == 1
lst1 = filter(is_odd,[1,2,3,4,5,6,7,8,])
# [1, 3, 5, 7]
3.sorted
# sorted()函数可以对可迭代对象进行排序,并且可以人为指定排序的依据以及方式。
l1 = [21, 12, 53, 64, 76, 32, 11, 22]
res = sorted(l1)
print(res) # 默认升序
常见内置函数
1.abs() 绝对值
print(abs(-100)) # |-100| = 100
2.all() 所有数据值对应的布尔值为True结果才是True 佛iu则返回False、
print(all([0, 1, 2, 3])) # False
print(all([1, 2, 3])) # True
3.any()
# 所有数据值对应的布尔值有一个为True就是True否则返回False
print(any([0, None, '', 1])) # True
print(any([0, None, ''])) # False
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)) # false
print(callable(index)) # True
7.chr() ord() 基于ASCII码表做数字与字母的转换 大写英文65-90 小写 97-122
print(chr(65)) # A
print(ord('A')) # 65
8.dir() 返回括号内对象能调用的名字
print(dir('hello'))
9.divmod() 元组 第一个数据为整除数 第二个是余数
res = divmod(100, 2)
print(res) # (50, 0)
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)) #(9, 9)
if more:
page_num += 1
print('总页码为', page_num) # 总页码为:500
10. enumerate()
# 一般用于for循环。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) # 报错 只能识别简单的python代码 具有逻辑性的都不行
exec(s2) # 可以识别具有一定逻辑性的python代码
12.hash() 哈希加密
print(hash('jason'))
13. id() input() isinstance()
# id() 函数用于获取对象的内存地址
input() 提示用户输入信息 实现人机交互
isinstance() :
# isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
14.map() max() min()
# 映射函数 求最大值 求最小值
15.open()
函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。
16.pow() 幂指数(次方)
print(pow(2, 2)) # 4
print(pow(2, 3)) # 8
print(pow(2, 4)) # 16
17.range() 范围
18.round() 四舍五入\但是98.5 5不会进1
print(round(98.3)) # 98
print(round(98.6)) # 99
19.sum() #求和
print(sum([11, 22, 33, 44, 55, 66])) # 231
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__()) #迭代取值 for循环本质
一旦__next__取不到值 会直接报错
4.注意事项
可迭代对象调用__iter__会成为迭代器对象
迭代器对象如果还调用__iter__不会有任何变化 还是迭代器对象本身
for循环本质
for 变量名 in 可迭代对象:
循环体代码
"""
1.先将in后面的数据调用__iter__转变成迭代器对象
2.依次让迭代器对象调用__next__取值
3.一旦__next__取不到值报错 for循环会自动捕获并处理
"""
异常捕获/处理
1.异常
异常就是代码运行报错 行业俗语叫bug
代码运行中一旦遇到异常会直接结束整个程序的运行 我们在编写代码的过程中药尽可能避免
2.异常分类
语法错误
不允许出现 一旦出现立刻改正 否则提桶跑路
逻辑错误
允许出现的 因为它一眼发现不了 代码运行之后才可能会出现
3.异常结构
错误位置
错误类型
错误详情
标签:index,return,复习,res,第三周,print,def,函数
From: https://www.cnblogs.com/wei0919/p/16797336.html