文件操作
在开始介绍之前,先介绍一下有关计算机文件存存储的一些知识:
"""
计算机是以二进制的形式来存储数据的,它只认识 0 和 1 两个数字,
我们在屏幕上看到的文字,在存储之前都被转换成了二进制(0和1),
在显示时也要根据二进制找到对应的字符。
特定的文字需要对应着固定的二进制,否则在转换时将发生混乱。
那么,怎样将文字与二进制对应起来呢?
这就需要有一套规范,这样的一套规范就称为字符编码(Character Encoding)。
字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字
计算机是谁发明的?不是中国人,所以计算机出来的时候他肯定不会先考虑优先显示中文。
它肯定优先考虑它经常用的英文字符。
所以最先考虑仅仅是让计算机识别英文字符,于是诞生了ASCII表(美国信息交换标准代码)
一个英文字符对应1Bytes
一个中文字符对应2Bytes
1Bytes=8bit,8bit最多包含256个数字,可以对应256个字符,足够表示所有英文字符
2Bytes=16bit,16bit最多包含65536个数字,可以对应65536个字符,足够表示所有中文字符
美国人用的计算机里使用字符编码标准是ASCII、
中国人用的计算机里使用字符编码标准是GBK、
日本人用的计算机里使用字符编码标准是Shift_JIS
这些字符编码和 ASCII 一样,只考虑本国的语言文化,不兼容其它国家的文字。
这样做的后果就是,一台计算机上必须安装多套字符编码,否则就不能正确地跨国传递数据,
例如在中国编写的文本文件,拿到日本的电脑上就无法打开,或者打开后是一堆乱码。
这么乱极大了阻碍了不同国家的信息传递,于是联合国出面,发誓要解决这个混乱局面。
因此,**Unicode**应运而生。**Unicode**把所有语言都统一到一套编码里,
这样就不会再有乱码问题了。unicode于1990年开始研发,1994年正式公布,
unicode固定使用四个字节来存储一个字符
在内存当中我们使用的就是unicode
utf-8是针对Unicode的可变长度字符编码:一个英文字符占1Bytes,一个中文字符占3Bytes,生僻字用更多的Bytes存储
在计算机内存中,统一使用**Unicode**编码,当需要保存到硬盘或者需要传输的时候,就转换为**UTF-8**编码。
用记事本编辑的时候,从文件读取的**UTF-8**字符被转换为**Unicode**字符到内存里,
编辑完成后,保存的时候再把Unicode转换为UTF-8*存到文件。
"""
1. 打开文件
在进行文件读写之前,首先要打开文件:
- python提供了一个内置函数
open()函数
,该函数打开指定文件
open(file_name [, access_mode][, buffering])
```
>>>该函数返回一个对象
>>>在上面的语法格式中,只有第一个参数是必须的,该参数代表文件打开路径。注意,打开文件的前提是该文件存在。
>>>access_mode和buffering参数都有默认值,他们是可选的。
```
- 在打开文件之后,就可以调用文件对象的属性和方法了。
>>>file.closed 返回文件是否关闭
>>>file.mode 返回打开文件的访问方式
>>>file.name 返回文件的名称
下面我们在D根目录下盘创建一个名为: open_test.py
的文件,然后运行下面语句,可得相应输出:
# 以默认的方式打开文件: 默认读模式:r
f = open('D:/open_test.py')
print(f.encoding) # 访问文件的编码方式:cp936
print(f.mode) # r
print(f.closed) # False
print(f.name) # D:/open_test.py
f.close()
print(f.closed) # True
- 文件打开模式
模式 | 功能 | 其他描述 |
---|---|---|
r | 只读模式 | 指针位置:开头 |
w | 写模式 | 指针位置:开头 |
a | 追加模式(写模式) | 指针位置:结尾 |
+ | 读模式,与其他模式结合 | r+:读写模式 w+:读写模式 |
b | 二进制模式,可与其他模式混合使用 | rb 代表二进制只读模式 rb+ 代表二进制读写模式 ab 代表二进制追加模式 |
r+ | 读写模式 | 指针位置:开头 |
a+ | 读写模式 | 指针位置:结尾 |
# w 代表写模式,w+代表读写模式,但是实际上差别不大
# 因为使用这两种方法打开文件的时候,open函数会立即清空文件内容,
# 所以这两种都无法读取文件内容
# 所以如果希望open打开文件后,文件内容能被保留下来,那就不能使用 w 或 w+ 模式
'''
注意,使用 r ,r+ ,模式打开文件,要求被打开的文件本身是存在的
使用,w , w+ , a , a+,模式打开文件,则该文件可以不存在,open()函数会自动创建新文件
'''
- 关于
buffering
参数,这里介绍一些相关知识:
# 缓冲
'''
总所周知,计算机外设(比如硬盘、网络)的I/O速度远远低于访问内存的速度
而程序执行I/O时要么将内存中的数据写入外设,要么将外设中的数据读取到内存
如果不使用缓冲,就必须等外设输入或输出一个字节后,内存中的程序才能输出或输入一个字节
这意味着内存中的程序大部分时间都处于等待状态
内存中程序的读写速度很快,如果不使用缓冲,则程序必须等待外设进行同步读写。
# 打个比喻,就像在一条很堵的马路上开着跑车,必须等前面车开一点,跑车才能前进一点
因此,一般建议打开缓冲
在打开缓冲后,当程序执行输出时,程序会先将数据输出到缓冲区中
而不用等待外设同步输出,当程序把所有数据都输出到缓冲区中之后
程序就可以区干其他事情了,留着缓冲区同步到外设既可;
反过来,当程序执行输入时,程序会先等外设将数据读入缓冲区中,而不用等待外设同步输入
'''
'''
在使用open()函数时,如果第三个参数是 0 或 False,那么该函数打开的文件就是不带缓冲区的;
如果第三个参数是 1 或True ,则该函数打开就是带缓冲区的,此时程序执行I/O将具有更好的性能
如果第三个参数是大于 1 的整数,则该整数指定缓冲区的大小(单位是字节)
如果第三个参数为任何负数,则代表使用默认的缓冲区大小
'''
打开文件之后,接下来就可以操作文件内容了!!!
2. 读取文件
python既可以使用使用文件对象的方法来读取文件,也可使用其他模块来读取文件
- 按字节或字符读取
'''
文件对象提供了read()方法来按字节或字符读取文件内容,到底是读取字节还是字符,取决于是否使用了 b 模式:
>>>如果使用了 b 模式,则每次读取一个字节;
>>>如果没有使用 b 模式,则每次读取一个字符。
在调用该方法时可传入一个整数作为参数,用于指定读取多少字节或字符
'''
例如,下面程序采用循环来读取整个文件内容:
f = open('D:/test.txt', 'r', True, encoding= 'utf-8')
while True:
ch = f.read(1) # 每次读取一个字符
if not ch: break # 如果没有读取到数据,则跳出循环
print(ch, end = '') # 输出 ch
f.close()
# 上面采用循环的方式依次读取文件内容(因此程序没有使用 b 模式),
# 每读取到一个字符,程序就输出该字符
# 当程序读写完文件之后,应立即调用 close() 方法来关闭文件
# 这样可以避免资源泄露
下面提供一个更好更安全的关闭文件的方法:
# 将上面的程序改成如下形式
f = open('D:/test.txt', 'r', True, encodeing = 'utf-8')
try:
while True:
ch = f.read(1)
if not ch: break
print (ch, end = '')
finally:
f.close()
如果在调用read()
方法时不传入参数,该方法会默认读取文件全部内容,例如:
f = open('D:/test.txt', 'r', True, encoding= 'utf-8')
print(f.read()) # 直接读取文件全部内容
f.close()
'''
从上面程序可以发现问题:当使用open()函数打开文本文件时,
程序指定的是哪种字符集呢?总是使用操作系统的字符集,比如Windows平台,open()函数总是默认使用GBK字符集
但是在open()函数里面指定了字符集为utf-8,所以是以这个字符集读取
因此,如果没有指定字符集,上面程序读取的test.txt则必须使用GBK字符集保存;否则,程序就会出现UnicodeDecodeError错误
'''
下面是详细解决方案:
# 如果要读取文件所使用的字符集合当前操作系统字符集不匹配,则有两种解决办法:
# >>使用二进制模式读取,然后用bytes的decode()方法恢复成字符串
# >>利用codes模块的open()函数来打开文件,该函数在打开文件时允许使用指定字符集
# 下面程序使用二进制模式来读取文本:
f = open('D:/open_test1.py', 'rb')
print(f.read().decode('utf-8')) # 调用bytes的decode()方法将字节内容恢复成字符串
f.close()
'''
上面程序调用open()函数时,传入了 rb 模式,这表明采用二进制模式读取文件
此时文件对象的 read() 方法返回的是bytes对象,程序可调用bytes对象的decode()
方法将它恢复成字符串。由于open_test1.py是以UTF-8的格式保存的,、
因此程序需要使用decode()方法恢复字符串时显示使用UTF-8字符集
'''
# 下面程序使用了codes模块的open()函数来打开文件,此时可以显示地指定字符集
import codecs
f = codecs.open('D:/read_test2.py', 'r', 'utf-8')
while True:
ch = f.read(1) # 每次读取一个字符
if not ch: break
print(ch, end = '')
f.close()
# 上面在调用open()函数时显式地指定使用UTF-8字符集,这样程序在读取文件内容时就完全没有问题了
- 按行读取
如果程序要求按行读取,通常只能使用文本方式来读取
道理很简单,只有文本文件才有行的概念,二进制文件没有所谓行的概念
# 文件对象提供了如下两个方法来读取行:
# >>readline([n]) : 读取一行内容,如果指定了参数 n ,则只读取此行内的 n 个字符
# >>readlines() : 读取文件内所有行
readline()
:每次读取文件一行
import codecs
f= codecs.open('D:/readline_test.py', 'r', 'utf_8')
while True:
line = f.readline() # 每次读取一行
if not line: break
print(line, end = '')
f.close()
# 采用逐行读取,当读取到文件尾时,该方法会返回空,程序因此推出循环
readlines()
:一次读取文件内所有的行
import codes
f = codecs.open('D:/readline_test.py', 'r', 'utf-8')
content = f.readlines() # 读取所有行,返回所有行组成的列表
print(content)
for ele in content:
print(ele, end = '')
f.close()
- 使用
fileinput
读取多个输入流
'''
fileinput模块提供了如下函数可以把多个输入流合并在一起:
>>fileinput.input(files = None, inplace = False, backup = ', bufsize = 0, mode = 'r', openhook = None):
该函数中的files参数用于指定多个文件输入流。该函数返回一个FileInput对象。
当程序使用上面的函数创建了FileInput对象之后,即可通过for循环来遍历文件的每一行。
此外,fileinput还提供了如下全局函数来判断正在读取文件信息
>>fileinput.filename() :返回正在读取的文件的文件名
>>fileinput.fileno() :返回当前文件的文件描述符(file descriptor),该文件描述符是一个整数
补充:文件描述符就是一个文件的代号,其值为一个整数
'''
方法 | 功能 |
---|---|
fileinput.lineno() | 返回当前读取的行号 |
fileinput.filelineno() | 返回当前读取的行在其文件中的行号 |
fileinput.isfirstline() | 返回当前读取的行在其文件中是否为第一行 |
fileinput.isstdin() | 返回最后一行是否从 sys.stdin读取。程序可以使用“_”代表从sys.stdin读取 |
fileinput.nextfile() | 关闭当前文件,开始读下一个文件 |
fileinput.close() | 关闭FileInput对象 |
'''
从上面也可以看出,fileinput也存在一个缺陷:
在创建FileInput对象时不能指定字符集,
因此它所读取文档文件的字符集必须与操作系统默认的字符集保持一致。
当然,如果文本文件的内容是纯英文,则不存在字符集的问题
'''
示范使用fileinput
模块来读取多个文件
# # 一次性读取多个文件
# for line in fileinput.input(files = ('D:/info.txt', 'D:/info2.txt')):
# print(fileinput.filename(), fileinput.filelineno(), line, end = '')
# fileinput.close() # 关闭文件流
# 由于这里默认的是GBK字符集,而我们的文本文件时UTF-8字符集,所以就不允许了
# 上面我们创建的info文本文件包含了其他非英文字符,下面我们可以创建两个只包含英文字符的文本文件
# 这里是可以读取的
# 上面程序使用file.input直接合并了info.txt和info2.txt两个文件,这样程序可以直接遍历读取这两个文件
import fileinput
# 一次性读取多个文件
for line in fileinput.input(files = ('D:/english.txt', 'D:/english2.txt')):
print(fileinput.filename(), fileinput.filelineno(), line, end = '')
fileinput.close() # 关闭文件流
- 文件迭代器
实际上,文件本身是可遍历的,就像一个序列一样,
因此,程序完全可以使用for循环来遍历文件内容
# 使用for循环读取文件内容:
import codecs
f = codecs.open('D:/readline_test.py', 'r', 'utf-8')
for line in f:
print(line, end = '')
f.close()
如果有需要,程序也可以使用list()
函数将文件转换成list列表,就像文件对象的readlines()
的返回值一样
# 例如:(程序清单同上)
# 将文件转换成list列表
print(list(codecs.open('D:/readline_test.py', 'r', 'utf-8')))
此外,sys.stdin
也是一个类文件对象(类似于文件的对象,python的很多I/O流都是类文件对象),
因此,程序同样可以使用for循环遍历sys.stdin
,这意味着程序可以通过for
循环来获取用户的键盘输入
# 例如:
# import sys
# 使用for循环遍历输入标准
# print('请输入:', end = '')
# for line in sys.stdin:
# print('用户输入:', line, end = '')
# print()
# print('请输入:', end='')
- 使用
with
语句
在前面的程序中,我们都采用程序主动关闭文件的方式,实际上,python提供了with
语句来管理资源关闭
比如我们可以把打开的文件放在with语句中,这样with语句就会帮我们自动关闭文件。
with context_expression [as target(s)]:
with 代码块
# context_expression用于创建可自动关闭的资源
方法对比:
# 1
file = open('D:/hello.txt',mode='r',encoding='utf-8') #对操作系统发起请求 底层不是python代码在做 r read 读
str = file.read()
print(str)
file.close() #close 关闭
# 2
with open('D:/hello.txt','r') as f:
print(f.read())
# 两个方法运行结果相同
3. 写文件
# project:写文件
'''
如果以 r+ , w , w+ , a , a+ 模式打开文件,则都可以写入
当以 r+、w、w+ 模式打开文件时,文件指针位于文件开头处;
当以 a、a+ 模式打开文件时,文件指针位于结尾处。
另外,当以 w 或 w+ 打开文件时,程序会立即清空文件的内容
'''
# 文件指针的概念
'''
文件指针用于表明文件读写的位置。假如把文件看成一个水流,
文件中每个数据(以 b 模式打开,每个数据就是一个字节;以普通模式打开,每个数据就是一个字符)
就相当于一个水滴,而文件指针就表明了文件将要读写哪个位置
'''
'''
文件对象提供了以下方法来操控文件指针:
>>>seek(offset[,whence]) : 该方法把文件指针移到指定位置
>>当whence为 0 时(这是默认值),表明从文件开头计算,比如将offset设为 3 ,就是将文件指针移动到第 3 处;
>>当whence为 1 时,表明从指针当前位置开始计算,比如文件指针当前在第 5 处,将 offset 设为 3 ,就是将文件指针移动到第 8 处;
>>当whence为 2 时,表明从文件结尾开始计算,比如将offset设为 -3 ,表明将文件指针移动到文件结尾倒数第 3 处
简单可总结如下:
#offset参数:指针移动的字节数
#whence参数:
# 0 默认模式,指针移动的字节数以文件开头作为参考
# 1 该模式下,指针移动的字节数以当前位置作为参考
# 2 该模式下,指针移动的字节数以文件末尾位置作为参考
>>>tell() :判断文件指针位置
此外,当程序使用文件对象读写数据时,文件指针会自动向后移动:
读写了多少个数据,文件指针就自动向后移动多少个数据
'''
# 示范文件指针操作:
f = open('D:/english.txt', 'rb')
print(f.tell()) # 0
f.seek(3)
print(f.tell()) # 3
# 读取一个字节,文件指针自动向后移一个数据
print(f.read(1)) # b'e'
print(f.tell()) # 4
f.seek(5)
print(f.tell()) # 5
f.seek(5, 1)
print(f.tell()) # 10
f.seek(-10, 2)
print(f.tell()) # 39
print(f.read(1)) # b'k'
print('============================================')
# 输出内容
# 文件对象提供的写文件的方法主要有两个:
# >>write(str 或bytes): 输出字符串或字节串。
# 只有以二进制模式(b 模式)打开的文件才能写入字节串
# >>writelines(可迭代对象):输出多个字符串或多个字节串
# 示范:
import os
f = open('H:/txt.txt', 'w+')
# os.linesep代表当前操作系统上的换行符
f.write('我爱python' + os.linesep)
f.writelines(('床前明月光'+ os.linesep,\
'疑是地上霜。'+ os.linesep,\
'举头望明月'+ os.linesep,\
'低头思故乡。'+ os.linesep))
f.close()
# 当使用方法输出文件时,程序会使用当前操作系统默认的字符集。
# 如果需要使用指定的字符集来输出文件,则可以使用二进制形式————
# 程序先将所输出的字符串转换成指定字符集对应的二进制数据(字节串),然后输出二进制数据
# 示范使用二进制数据输出:
# 通过这种方法来实现UTF-8字符集保存文件
import os
f = open('H:/y.txt', 'wb+')
# os.linesep代表当前操作系统上的换行符
f.write(('我爱python'+ os.linesep).encode('utf-8'))
f.writelines((('床前明月光'+ os.linesep).encode('utf-8'),\
('疑是地上霜'+ os.linesep).encode('utf-8'),\
('举头望明月'+ os.linesep).encode('utf-8')))
# 每次允许上面程序都会向y.txt文件中追加一段内容
print('============================================')
#w write 只写模式:如果文件不存在,则会创建该文件,如果文件存在,则会清空该文件的内容
# with open('D:/song.txt',mode='w',encoding='utf-8') as f:
# f.write('她来听我的演唱会\n')
# f.write('夜的第七章\n')
# f.write('以父之名\n')
#copy文件
# with open('D:/song.txt','r',encoding='utf-8') as f:
# content = f.read()
# with open('D:/song2.txt','w',encoding='utf-8') as w:
# w.write(content)
#复用性
# with open('D:/song.txt','r',encoding='utf-8') as f,\
# open('D:/歌曲.txt','w',encoding='utf-8') as w:
# content = f.read()
# w.write(content)
#a 追加模式:如果文件存在时候会把指针移到文件最后面,不存在则会创建文件
# with open('D:/demo.txt',mode='a',encoding='utf-8') as f:
# f.write('\nhow are you?')
4. 文件操作模式详解(总结大全)
# 操作模式
# r 只读模式
# w 创建模式,若文件已存在,则覆盖旧文件
# a 追加模式,新数据会写到文件末尾
# t 默认
# 1,读写都必须以str(unicode)为单位
# 2,文本文件
# 3,必须指定encoding='utf-8'
# b 二进制模式 bytres
# 注意:t跟b必须配合r,w,a使用!如: 'wb'
# file = open('D:/hello.txt',mode='r',encoding='utf-8') #对操作系统发起请求 底层不是python代码在做 r read 读
# str = file.read()
# print(str)
# file.close() #close 关闭
#
# with open('D:/hello.txt','r') as f: # f=file= open('D:/hello.txt',mode='r',encoding='utf-8')
# print(f.read())
#r read 只读模式 只能看,不能改
#模拟用户登录 账号密码判断
# inp_username = input('请输入你的用户名:').strip() #去掉文本前后空格
# inp_password = input('请输入你的密码:').strip()
#
# #读取文本用户信息
# with open('D:/user.txt','r') as f:
# info = f.read() #读取内容
# username,password=info.split(':')
# if username==inp_username and password==inp_password:
# print('登陆成功!')
# else:
# print('用户名或者密码错误!')
#w write 只写模式:如果文件不存在,则会创建该文件,如果文件存在,则会清空该文件的内容
# with open('D:/song.txt',mode='w',encoding='utf-8') as f:
# f.write('她来听我的演唱会\n')
# f.write('夜的第七章\n')
# f.write('以父之名\n')
#copy文件
# with open('D:/song.txt','r',encoding='utf-8') as f:
# content = f.read()
# with open('D:/song2.txt','w',encoding='utf-8') as w:
# w.write(content)
#复用性
# with open('D:/song.txt','r',encoding='utf-8') as f,\
# open('D:/歌曲.txt','w',encoding='utf-8') as w:
# content = f.read()
# w.write(content)
#a 追加模式:如果文件存在时候会把指针移到文件最后面,不存在则会创建文件
# with open('D:/demo.txt',mode='a',encoding='utf-8') as f:
# f.write('\nhow are you?')
#实现用户注册
# name = input('请输入您的用户名:').strip()
# pwd = input('请输入你的密码:').strip()
# with open('D:/user.txt','a',encoding='utf-8') as f:
# info = '\n%s:%s\n'%(name,pwd)
# f.write(info)
# 混合模式
# r+ 读写
# with open('D:/hello.txt',mode='rt+',encoding='utf-8') as f:
# print(f.read())
# # f.write('\ni love china!')
# # print(f.read())
#
# # w+ 写读 mode='w+t'
#a+ 追加读 文件一打开光标就会文件尾部,写数据全是追加模式
# with open('D:/hello.txt',mode='a+t',encoding='utf-8') as f:
# print(f.read())
#
# f.write('\nhow are you?')
# f.write('\ni am fine!')
#
# print(f.read())
#b 模式
# t
#1,读写都以字符串(unicode)作为单位
#2,只能针对文本文件
#3,必须指定字符编码 encoding参数
# b binary 模式
#1,读写都是以bytes为单位
#2,可以针对所有文件
#3,一定不要去指定字符集编码
#错误示范 mode=rt t只能读文本
# with open('D:/a.mp4',mode='rt') as f:
# f.read()
#正确
# with open('D:/a.mp4',mode='rb') as f:
# print(f.read()) #从硬盘的二进制读入内存->直接读入
#在计算机中,只能存储二进制! 0101010110101 python是以bytes 字节来表示的
#copy
# with open('D:/a.mp4','rb') as read_f,open('D:/b.mp4','wb') as write_f:
# for line in read_f:
# write_f.write(line)
#
# #读操作
# f.read() #读取所有内容,执行完该操作后,文件指针自动移向文件末尾
# f.readline() #读取一行内容,光标移动到第二行首部
# f.readlines() #读取每一行的内容,放入列表中
#
# #写操作
# f.write() #针对文本模式,需要手动换行
# f.writelines(['i love china\n','i am fine!\n']) #文件模式
#属性了解
# f.readable() # able 能不能 文件是否可读
# f.writable() #文件是否可写
# f.closed #文件是否关闭
# f.flush() #立即将文件内容从内存刷到硬盘
# f.name #文件名
# with open('D:/hello.txt','rt',encoding='utf-8') as f:
# print(f.readable()) # able 能不能 文件是否可读
# print(f.writable()) # 文件是否可写
# print(f.closed) # 文件是否关闭
# print(f.encoding) #文件编码
# #f.flush() # 立即将文件内容从内存刷到硬盘
# print(f.name) # 文件名
#文件指针控制
# with open('D:/hello.txt','rt',encoding='utf-8') as f:
# data = f.read(5)
# print(data)
#seek(a参数,b参数) 指定指针特定位置
#a参数:指针移动的字节数
#b参数:
# 0 默认模式,指针移动的字节数以文件开头作为参考
# 1 该模式下,指针移动的字节数以当前位置作为参考
# 2 该模式下,指针移动的字节数以文件末尾位置作为参考
# f.tell() 获取文件指针当前位置
# with open('D:/hello.txt','rt',encoding='utf-8') as f:
# data = f.read(5)
# print(data)
# print(f.tell())
# with open('D:/hello.txt','rt',encoding='utf-8') as f:
# f.seek(9,0)
# print(f.tell())
# print(f.read())
# with open('D:/hello.txt','rt',encoding='utf-8') as f:
# f.seek(0,2)
# print(f.tell())
# print(f.read())
5. 小题目分享
# 一:
# 1只公鸡5块;1只母鸡3块;3只小鸡1块,100只鸡100块钱 打印出所有可能的组合
for i in range(0,21):
for j in range(0,34):
for k in range(0,101):
if i+j+k==100 and 5*i+3*j+k/3==100: #满足条件
print('公鸡:{},母鸡:{},小鸡:{}'.format(i,j,k))
#母鸡:25,小鸡:75
# 二
# 程序运行后获取到用户输入字符串
# 1. 打印第一个字符
# 2. 打印最后一个字符
# 3. 打印倒数第三个字符
# 4. 打印前两个字符
# 5. 倒序打印字符
# 6. 如果字符长度是奇数,则打印中间字符
user_str = input('请输入一个字符串:')
print(user_str[0])
print(user_str[-1])
print(user_str[-3])
print(user_str[0: 2])
print(user_str[::-1])
if len(user_str)/2 != 0:
print(user_str[int((len(user_str) - 1) / 2)])
else:
print('字符串的长度不是奇数')
# 进度条
for i in range(20):
sys.stdout.write('·')
sys.stdout.flush()
time.sleep(0.25)
6. 案例分享
- 监控文件改动
#监控文件改动
import time
with open('D:/hello.txt','rb') as f:
f.seek(0,2) #指针移到文件末尾
while True:
line = f.readline() #等待内容输入
if(len(line))==0:
time.sleep(2) #如果没有内容,就进行等待
else:
print(line.decode('utf-8'),end=' ')
- 银行账户模拟
'''
运行程序前,请先在 D 盘创建一个 python_demo 的文件夹
该文件夹用以保存创建以保存用户信息等相关内容的文本文件
'''
'''
运行程序前,请先在 D 盘创建一个 python_demo 的文件夹
该文件夹用以保存创建以保存用户信息等相关内容的文本文件
'''
import os
#登录功能
def login():
print('登录')
flag = 1
number = 0
while number < 3:
print('输入 quit 退出')
user_name = input("请输入用户名:")
if user_name == 'quit':
return
print('输入 quit 退出')
password = input('请输入用户密码:')
if password == 'quit':
return
with open('D:/python_demo/userinfo.txt', 'rt+', encoding='utf-8') as f:
while True:
line = f.readline().split(':') # 每次读取一行
if line == ['']: # 读取到空,已读完文件,结束本次循环
number += 1
break
user_nameMsg, passwordMsg = line
if user_name == user_nameMsg and password == passwordMsg.strip('\n'):
print('登录成功!!')
flag = 0
break
if flag: # 如果登录成功就不进行下面的判断
if number == 3:
print('次数已用完!')
BeforeLoginChoice()
else:
print('用户名或密码错误!')
print('您还有%s次机会' % (3 - number))
else:
break # flag = 0, 登录成功,直接退出外层循环
return user_name
# 充值
def TopUp(user_name):
print('充值')
with open('D:/python_demo/%s.txt'%(user_name), 'r', encoding='utf-8') as f:
RemainingSum = float(f.readline().strip()) # 这里先假设用以保存用户信息的文件中只有用户的余额
with open('D:/python_demo/%s.txt'%(user_name), 'w+', encoding='utf-8') as f:
print('输入 quit 退出')
TupUpMoney = (input('请输入充值金额:'))
if TupUpMoney == 'quit':
return
f.write(str(RemainingSum + float(TupUpMoney)))
print('充值完成!')
#转账
def transfer(user_name):
print('转账')
while True:
with open('D:/python_demo/%s.txt' % (user_name), 'r', encoding='utf-8') as ReadUserMoney:
RemainingUserMoney = float(ReadUserMoney.read()) # 拿出用户的余额
print('输入 quit 退出')
TransferTarget = input('请输入要转入的账户:')
if TransferTarget == 'quit':
return
print('输入 quit 退出')
TransferMoney = input('请输入转账金额:')
if TransferMoney == 'quit':
return
ReadTargetMoney = open('D:/python_demo/%s.txt' % (TransferTarget), 'a+', encoding='utf-8')
if ReadTargetMoney.tell() == 0:
print('用户不存在,请重新输入!')
ReadTargetMoney.close()
os.remove('D:/python_demo/%s.txt' % (TransferTarget)) # 如果用户不存在,删除创建的不存在用户文本文件
break
else:
with open('D:/python_demo/%s.txt' % (TransferTarget), 'r', encoding='utf-8') as ReadTargetMoney:
TransferMoney = float(TransferMoney)
if TransferMoney > RemainingUserMoney:
print('余额不足')
break
else:
RemainingTargetMoney = float(ReadTargetMoney.read().strip('\n')) # 先拿出要转入用户的余额
with open('D:/python_demo/%s.txt' % (TransferTarget), 'w+',
encoding='utf-8') as WriteTargetMoney:
WriteTargetMoney.write(str(TransferMoney + RemainingTargetMoney))
with open('D:/python_demo/%s.txt' % (user_name), 'w+', encoding='utf-8') as WriteUserMoney:
WriteUserMoney.write(str(RemainingUserMoney - TransferMoney))
print('转账完成。')
break # 结束外层循环
#查询余额
def check(user_name):
print('查询余额')
with open('D:/python_demo/%s.txt' % (user_name), 'r', encoding='utf-8') as f:
money = f.read()
print('您的余额为:'+ money)
# print(trans.run(float(money)))
#提现
def withdraw(user_name):
print('提现')
while True:
with open('D:/python_demo/%s.txt' % (user_name), 'r', encoding='utf-8') as ReadFile:
print('输入 quit 退出')
CashWithdraaw = (input('请输入提现金额:')) # 获取用户的提现金额
if CashWithdraaw == 'quit':
return
RemainingMoney = float(ReadFile.read().strip('\n')) # 拿出用户的余额
if float(CashWithdraaw) > RemainingMoney:
print('余额不足,请重新输入')
else:
with open('D:/python_demo/%s.txt' % (user_name), 'w+', encoding='utf-8') as WriteFile:
WriteFile.write(str(RemainingMoney - float(CashWithdraaw)))
print('提现完成')
break
#注册
def register():
print('注册')
while True:
print('输入 quit 退出')
user_name = input('请输入用户名(只能包含数字):').strip()
if user_name == 'quit':
return
if not user_name.isdigit():
print('用户名只能是纯数字,请重新输入!')
continue
with open('D:/python_demo/userinfo.txt', 'a+', encoding='utf-8') as f:
f.seek(0)
if user_name in f.read():
print('用户名已存在,请重新输入!')
continue
else:
break
while True:
print('输入 quit 退出')
password1 = input('请设置您的用户密码:').strip()
if password1 == 'quit':
return
print('输入 quit 退出')
password2 = input('请确认您的密码:').strip()
if password2 == 'quit':
return
if password1 == password2:
flag = 1
break
else:
print('两次输入密码不一致,请重新输入。')
with open('D:/python_demo/userinfo.txt', 'a+', encoding='utf-8') as f:
f.write(user_name+':')
f.write(password2+'\n')
if flag: # 用户注册成功,则创建一个文件用以保存用户信息
f = open('D:/python_demo/%s.txt'%(user_name),mode='w',encoding='utf-8')
f.write('0') # 初始注册,用户余额为 0
f.close()
print('注册成功')
#函数字典
BeforLoginDict = {
'1':login,
'2':register
}
AfterLoginDict = {
'1':TopUp,
'2':transfer,
'3':check,
'4':withdraw,
}
def AfterLoginChoice(user_name):
while True:
print(
'''
0 退出
1 充值
2 转账
3 查询余额
4 提现
'''
)
# 接受用户的选择
choice = input('请输入您的选项(0-4):').strip()
if not choice.isdigit():
print('请输入符合要求的数字!')
continue
if int(choice) > 4 or int(choice) < 0:
print('请输入符合要求的数字!')
continue
str(choice)
if choice == '0':
break
if choice in AfterLoginDict:
AfterLoginDict[choice](user_name)
def BeforeLoginChoice():
while True:
print(
"""
0 退出
1 登录
2 注册
"""
)
# 接受用户的选择
choice = input('请输入您的选项(0-2):').strip()
if not choice.isdigit():
print('请输入符合要求的数字!')
continue
if int(choice) >= 4 or int(choice) < 0:
print('请输入符合要求的数字!')
continue
str(choice)
if choice == '0':
break
if choice == '2':
BeforLoginDict[choice]()
if choice == '1':
user_name = BeforLoginDict[choice]()
AfterLoginChoice(user_name)
BeforeLoginChoice()