1. 文件的高级应用
1.1 可读可写
r+: 在后面追加,即可读又可写(尽量不要使用)
with open('test.py','r+',encoding='utf8') as fr:
data = fr.read()
print(fr.writable())
fr.write('x = 10')
print(data)
w+: 清空文件的功能是w提供的,w+更不要使用
with open('test.py','w+',encoding='utf8') as fr:
# print(fr.writable())
# fr.write('x = 10')
data = fr.read()
print(data)
a+:有追加的功能,a的指针在末尾,a+功能也没有
with open('test.py','a+',encoding='utf8') as fr:
fr.seek(1,0)
data = fr.read() # 指针在末尾
print(data)
fr.write('x = 10')
fr.flush()
1.2 指针的应用(移动指针)
文件的内置方法:seek, tell, read(n), truncate
1.2.1 seek
0相当于文件头开始;1相当于当前文件所在位置;2相当于文件末尾
with open('test.py','r',encoding='utf8') as fr:
fr.seek(1) # 1表示位移1位,默认从文件头开始
fr.seek(1,0) # 1表示偏移1位,0表示从头开始
fr.seek(2, 1) # 1表示偏移1位,0表示从头开始
fr.seek(0, 2) # 0表示偏移0位,2表示文件末开始,把指针移到文件末
print(fr.read())
1.2.2 tell
每次统计都是从文件开头到当前指针所在位置
with open('test.py', 'r', encoding='utf8') as fr:
fr.seek(2,0)
print(fr.tell())
1.2.3 read(n)
读几个字符/几个字节
with open('test.py', 'r', encoding='utf8') as fr:
print(fr.read(5))
1.2.4 truncate
truncate(n)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate()要在r+或a或a+等模式下测试效果。它的参照物永远是文件头。并且truncate()不加参数,相当于清空文件。
with open('test.py', 'a', encoding='utf8') as fr:
fr.truncate(2) # 把2个字符后面的东西全清空
2. 文件修改的两种方式
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式。
2.1 方式一
将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)。
import os
import time
with open('test.py','r',encoding='utf8') as fr,
open('test_swap.py','w',encoding='utf8') as fw:
data = fr.read() # 全部读入内存,如果文件很大,会很卡
data = data.replace('下','小') # 在内存中完成修改
fw.write(data) # 新文件一次性写入原文件内容
time.sleep(5)
os.remove('test.py') # 删除文件
os.rename('test_swap.py','test.py') # 重命名文件
2.2 方式二
将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件。
import os
with open('test.py', 'r', encoding='utf8') as fr,
open('test_swap.py', 'w', encoding='utf8') as fw:
for i in fr:
i = i.replace('小','大')
fw.write(i)
os.remove('test.py') # 删除文件
os.rename('test_swap.py','test.py') # 重命名文件
总而言之,修改文件内容的思路为:以读的方式打开原文件,以写的方式打开一个新的文件,把原文件的内容进行修改,然后写入新文件,之后利用os模块的方法,把原文件删除,重命名新文件为原文件名,达到以假乱真的目的。
3. 函数的定义
在程序中,函数就是具备某一功能的工具,事先将工具准备好就是函数的定义,遇到应用场景拿来就用就是函数的调用。
定义函数的方式:
'''
def 函数名(): # 定义阶段
"""函数注释写在这里""" # 函数相当于工具,注释相当于工具的说明书
<代码块>
# 使用 # 调用阶段
函数名()
'''
## 定义阶段不执行函数体代码,只检测语法错误(牢记)
def func():
'''func函数的注释'''
# todo:未来写一个函数
pass
print(func.__doc__) # 记住 # 打印注释
eg:
def register():
'''注册函数'''
username = input('请输入你的用户名:')
pwd = input('请输入你的密码:')
with open('user_info.txt','a',encoding='utf8') as fa:
fa.write(f'{username}:{pwd}')
def login():
'''登录函数'''
username = input('请输入你的用户名:')
pwd = input('请输入你的密码:')
with open('user_info.txt', 'r', encoding='utf8') as fr:
data = fr.read()
user_list = data.split('|')
print(user_list)
user_info = f'{username}:{pwd}'
if user_info in user_list:
print('登录成功')
else:
print('登陆失败')
register() # 调用
login() # 调用
4. 函数的三种定义方式
4.1 无参函数
在函数阶段括号内没有参数,称为无参函数。需要注意的是:定义时无参,意味着调用时也无需传入参数。
def add(): 工具可以单独使用
'''无参函数'''
x = input('num1:')
y = input('num2:')
print(int(x) + int(y))
add()
4.2 有参函数
在函数定义阶段括号内有参数,称为有参函数。需要注意的是:定义时有参,意味着调用时也必须传入参数。
def add(x,y): # 这个工具不能单独使用,必须要加个配件,才能使用
'''有参函数'''
print(int(x) + int(y))
x = input('num1:')
y = input('num2:')
add(x,y)
4.3 空函数
空函数:定义了函数,啥都没有
当你只知道你需要实现某个功能,但不知道该如何用代码实现时,你可以暂时写个空函数,然后先实现其他的功能。
def func(): # 只知道工具叫什么名字,但不知道如何造这个工具
pass
5. 函数的调用
def add(x,y):
print(x+y)
add(10,20) # 函数的调用
6. 函数的返回值
函数的返回值:函数内部代码经过一些列逻辑处理获得的结果。
def add(x,y):
# 逻辑
print(x + y)
# return x+y # 函数的返回值;终止函数(跳出函数)
print(1)
print(2)
res = add(1,2) # 默认返回None
print(res)
return是一个函数结束的标志,函数内可以有多个return,只要执行到return,函数就会执行。
def add(x,y):
# return (x,y,x+y) # return可以返回任意数据类型
return x,y,x + y # return可以返回任意数据类型,不加括号返回多个值时,默认用元祖的形式返回
x,y,z = add(1,2)
print(x,y,z)
7. 函数的参数
7.1 形参
形参:定义阶段才有形参,形式参数,啥也没用,只是占个位置,具有描述意义,本质就是变量名
7.2 实参
实参: 调用阶段才有实参,实际的参数,具有具体的值
def add(num1,num2): # 形参
"""有参函数"""
print(int(num1) + int(num2))
add(1,2) # 实参
7.3 位置参数
在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参。
在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参。
def add(num1,num2): # 形参
"""有参函数"""
print(num1)
print(num2)
print(int(num1) + int(num2))
add(1,2) # 实参
def shopping(name = 'nick'): # 形参经常会引用同一个值
goods_dict = {1:'特斯拉',2:'奔驰',3:'劳斯莱斯'}
print(f'恭喜你{name},得到{goods_dict[1]}一个')
shopping('bob')
两个位置形参,就必须得要两个位置实参对应,从左到右一一对应
默认形参:不需要传参,可以使用默认值;传参就使用你传的值,默认形参必须放到位置形参后面
7.4 关键字实参
按照形参名给定具体的值,可以打破位置形参必须得一一对应传值的规定,位置实参必须在关键字实参之前,即在调用函数时,按照key=value的形式为指定的参数传值
def shopping(x,name = 'nick'): # 形参经常会引用同一个值
goods_dict = {1:'特斯拉',2:'奔驰',3:'劳斯莱斯'}
print(f'恭喜你{name},得到{goods_dict[x]}一个')
shopping(1,name='bob')
注意:
- 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
- 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
- 函数的参数尽量不要超过3个
- 需要用的时候用,一般用位置形参+位置实参