python学习笔记
今日内容概要
- 作业讲解
- 文件内光标的移动
- 文件数据修改
- 函数简介
今日内容详细
作业讲解
1.编写简易版本的拷贝工具
自己输入想要拷贝的数据路径 自己输入拷贝到哪个地方的目标路径
任何类型数据皆可拷贝
ps:个别电脑C盘文件由于权限问题可能无法拷贝 换其他盘尝试即可
# 1.先获取想要拷贝的数据路径
source_file_path = input('请输入想要拷贝的数据路径:').strip()
# 2.再获取拷贝到哪个地方的目标路径
target_file_path = input('请输入拷贝到哪个地方的目标路径:').strip()
# 3.读取想要拷贝的数据路径对应的内容,并写入到目标路径中
with open(r'%s' % source_file_path, 'rb') as f1, open(r'%s' % target_file_path, 'wb') as f2: # 合并代码并让路径添加r取消转移
for line in f1: # 循环读取文件中一行行内容
f2.write(line) # 依次写入新的文件
2.利用文件充当数据库编写用户登录、注册功能
文件名称:userinfo.txt
基础要求:
用户注册功能>>>:文件内添加用户数据(用户名、密码等)
用户登录功能>>>:读取文件内用户数据做校验
ps:上述功能只需要实现一次就算过关(单用户) 文件内始终就一个用户信息
拔高要求:
用户可以连续注册
用户可以多账号切换登录(多用户) 文件内有多个用户信息
ps:思考多用户数据情况下如何组织文件内数据结构较为简单
提示:本质其实就是昨天作业的第二道题 只不过数据库由数据类型变成文件
while True:
print("""
1.注册功能
2.登录功能
3.退出程序
""")
func_id = input('请输入功能编号:').strip()
if func_id == '1':
# 1.获取用户名
username = input('请输入用户名:').strip()
# 2.判断当前用户名是否已存在
# 2.1读取数据文件
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
# 2.2循环获取文件内容(一个个用户数据)
for line in f: # jason|123 kevin|321 tony|222
# 2.3拆分真实用户名比对
real_name = line.split('|')[0]
# 2.4判断用户名是否存在
if username == real_name:
print('用户名已存在')
break
else:
password = input('请输入密码:')
# 3.构造用户数据
user_data = '%s|%s\n' %(username, password)
# 4.打开并写入文件
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
f.write(user_data)
print(f'用户{username}注册成功')
elif func_id == '2':
# 1.获取用户数据
username = input('username:').strip()
password = input('password:').strip()
# 2.读取文件内容
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
# 2.1循环读取每个真实用户的数据
for line in f: # oscar|666 jerry|789
# 2.2拆分真实用户名和密码
real_name, real_pwd = line.split('|') # 注意密码后面有换行符
# 2.3判断用户输入的数据与真实数据是否一致
if username == real_name and password == real_pwd.strip('\n'):
print('登录成功')
break
else:
print('用户名或密码错误')
elif func_id == '3':
print('欢迎下次再来')
break
else:
print('请按指令输入')
文件读写模式补充
值 | 描述 |
---|---|
r | 只读取 ,文件不存在时则报错,文件存在文件内指针直接跳到文件开头 |
w | 只写入,文件不存在时会创建空文档,文件存在会清空文件,文件指针跑到文件开头 |
x | 只写入,文件已存在则无法创建文件和写入内容 |
a | 只追加写,文件不存在时会创建空文档,文件存在会将文件指针直接移动到文件末尾 |
t | 文本模式(默认值,与其他模式结合使用) |
b | 二进制模式(与其他模式结合使用) |
+ | 读写模式(与其他模式结合使用) |
rb | 以二进制格式打开一个文件用于只读 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 |
ab | 以二进制格式打开一个文件用于追加,如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 |
r+ | 打开一个文件用于读写 |
rb+ | 以二进制格式打开一个文件用于读写 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 |
a+ | 打开一个文件用于读写,如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 |
ab+ | 以二进制格式打开一个文件用于追加,如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 |
f = open('a.txt', 'r+', encoding='utf8') # 读取⽂件的时候使⽤utf8编码
content = f.read()
print(content)
f.write('123') # 使⽤r+模式可以直接读和写,先读后写的话:写⼊的时候从⽂本最后⾯开始,直接追加
# 如果是先写后读,则从⽂本开头写⼊,会覆盖对应个数的字符
f.close()
文件内光标的移动
在文本模式下read括号内的数字表示读取几个字符
with open(r'a.txt', 'r', encoding='utf8') as f:
data = f.read(3) # 读取3个字符
在二进制模式下read括号内的数字表示读取几个字节(英文一个字节 , 中文三个字节)
with open(r'a.txt', 'rb') as f:
data = f.reaad(3) # 读取3个字节
之前文件内指针的移动都是由读/写操作而被动触发的,若想读取文件某一特定位置的数据,则则需要用f.seek方法主动控制文件内指针的移动,详细用法如下:
seek(offset,whence)
offset:控制光标移动的字节数
whence:模式
0:默认模式,代表指针移动的的字节数是以文件开头为参照的
1:代表指针移动的字节数是以当前所在位置为参照的
2:代表指针移动的字节数是以文件末尾的位置为参照的
ps:1和2只能在二进制模式下使用,0无所谓
0模式的使用
# a.txt用utf8编码,内容:abc你好
with open(r'a.txt', 'r', encoding='utf8') as f:
f.seek(3,0) # 参照文件开头移动了3个字节
print(f.tell()) # 查看当前文件指针距离文件开头的位置,输出结果:3
print(f.read()) # 从第三个字节的位置读到文件末尾,输出结果:你好
# 注意:由于在t模式下,会将读取的内容自动解码,所以必须保证读取内容是一个完整中文数据,否则解码失败
with open(r'a.txt', 'rb') as f:
f.seek(6,0)
print(f.read().decode('utf8')) # 输出结果:好
1模式的使用
with open(r'a.txt', 'rb') as f:
f.seek(3,1) # 从当前位置往后移动3个字节,而此时的当前位置就是文件开头
print(f.tell()) # 输出结果:3
f.seek(4,1) # 从当前位置往后移动4个字节,而此时的当前位置为3
print(f.tell()) # 输出结果:7
2模式的使用
# a.txt用utf8编码,内容:abc你好
with open(r'a.txt', 'rb') as f:
f.seek(0,2) # 参照文件末尾移动0个字节,即直接跳到文件末尾
print(f.tell()) # 输出结果:9
f.seek(-3,2) # 参照文件末尾往前移动了3个字节
print(f.read().decode(utf8)) # 输出结果:好
# 小练习:实现动态查看最新一条日志的效果
import time
with open('access.log', 'rb') as f:
f.seek(0, 2)
while True:
line = f.readline()
if len(line) == 0:
# 没有内容
time.sleep(0.5)
else:
print(line.decode('utf8'), end='')
文件内数据修改
代码修改文件的方式:
1.覆盖写
先读取文件内容到内存,在内存中完成修改之后w模式打开该文件写入
2.重命名
先读取文件内容到内存,在内存中完成修改之后保存到另外一个文件中
再将原文件删除,将新的文件重命名为原文件
"""
机械硬盘存储数据的原理
1.数据的修改,其实是覆盖写
2.数据的删除,是由占有态变为自由态
"""
方式1:覆盖写
with open(r'demo.txt', 'r', encoding='utf8') as f:
data = f.read()
new_data = data.replace('dsb', 'nb')
with open(r'demo.txt', 'w', encoding='utf8') as f1:
f1.write(new_data)
"""
优点:硬盘只占用一块空间
缺点:数据量较大的时候会造成内存溢出
"""
方式2:重命名
import os
with open(r'demo.txt', 'r', encoding='utf8') as read_f, \
open('.demo.txt.swap', 'w', encoding='utf8') as wrife_f:
for line in read_f:
wrife_f.write(line.replace('nb', 'sb'))
os.remove('demo.txt') # 删除文件
os.remove('.demo.txt.swap', 'demo.txt') # 重命名文件
"""
优点:不会造成内存溢出
缺点:有那么一段时间需要占用硬盘两个地方的空间(可能),也可能实在内存中创建没有刷到硬盘
"""
函数简介
l1 = [1, 2, 3, 4, 5, 6]
print(len(l1)) # 不允许使用len 完成列表数据值个数统计
自定义统计方法
def my_len():
value_count = 0
for i in l1:
value_count += 1
print(value_count)
"""
我们自己瞎写的缺陷
1.只能统计某个固定的数据类型里面的数据值个数
2.没有产生新的值(返回值)
"""
"""
1.循环
在相同的位置反复执行相同的代码
2.函数
在不同的位置反复执行相同的代码
"""
print(len(l1))
print(my_len())
作业
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
pass
def registered_user(username, password):
"""
注册用户
:return:
"""
user_data = '%s|%s\n' % (username, password)
with open(r'userinfo.txt', 'a', encoding='utf8') as f:
f.write(user_data)
print(f'用户{username}注册成功')
def auth_user(username, password):
"""
用户身份验证
:return:
"""
with open(r'userinfo.txt', 'r', encoding='utf8') as f:
for line in f:
real_name, real_pwd = line.split('|')
if username == real_name and password == real_pwd.strip('\n'):
return True
else:
return False
while True:
print("""
1.注册功能
2.登录功能
""")
func_id = input('请输入功能编号:').strip()
if func_id == '1':
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
registered_user(username, password)
elif func_id == '2':
username = input('username:').strip()
password = input('password:').strip()
i = auth_user(username, password)
if i:
print('登录成功')
else:
print('登录失败')
else:
print('请按指令输入')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了