文件处理的其他操作2、迭代器、生成器、三元表达式、列表解析 第八天 2018.10.22
文件处理的其他操作:
文件处理b模式、其他方法
迭代器生成器:
迭代器协议、可迭代对象、强大的for循环、
两种生成器、生成器优点、生成器小结、三元表达式、列表解析、生成器表达式
文件最终以机器码存储在硬盘上,没有修改一说,新内容会覆盖掉原文件某部分的内容
a+可读可写---->新内容会按照大小覆盖掉光标之后的内容
1 f=open('test11.py','r+',encoding='utf-8') 2 f.write('hello')
文件处理b模式:
rb模式:
f=open('test11.py','rb') #b的方式不能指定编码
data=f.read()
print(data)
print(data.decode('utf-8')) #\x---->16进制
字符串---encode---->bytes
bytes----decode---->字符串
win系统文件读取换行\r\n Linux系统文件读取换行\n
wb模式:
f=open('test22.py','wb') #b的方式不能指定编码
f.write(bytes('1111\n',encoding='utf-8')) #bytes类型
f.write('杨件'.encode('utf-8'))
f=open('test22.py','ab') #b的方式不能指定编码
f.write('杨件'.encode('utf-8'))
open('a;ltxt','wt')#---->t为文本文件处理 二进制处理跨平台,win,Linux等等。
b模式对Linux没什么作用Linux默认二进制方式进行处理,b模式对win有用
w模式---->文件默认t模式(文本文档模式)
f.flush() #讲文件内容从内存刷到硬盘
pycharm,Word等会每过时间吧所写的自动刷到内存里
f.closed #文件如果关闭则返回True
f.encoding #查看使用open打开文件的编码
f.tell() #查看文件处理当前的光标位置
read是按字符移动光标的,其他按字节移动光标


f=open('b.txt','r',encoding='utf-8',newline='') #读取文件中真正的换行符号
f=open('b.txt','r+',encoding='utf-8',newline='') #读取文件中真正的换行符号
f.seek(3) #从开头开始算,将光标移动到第三个字节
f.truncate(10) #从开头开始算,将文件只保留从0-10个字节的内容,文件截取,但是w和w+除外
f=open('a.txt','r+',encoding='gb2312')
data=f.read() #原文件编码和追加编码不一样则会出现非需要的结果
print(data) #一个文件只有一个编码或者解码,且编码==解码
f.write('你好')
win系统默认gbk编码
f=open('seek.txt','r',encoding='utf-8')
print(f.tell())
f.seek(10)
print(f.tell())
f.seek(3) #默认从文件开头开始算
print(f.tell())
基于相对位置开始 不用默认模式时间需要用b的方式打开
f=open('seek.txt','rb')
print(f.tell())
f.seek(10,1)
print(f.tell())
f.seek(3,1) #1时,相对于上次光标的位置开始--->13
print(f.tell())
f=open('seek.txt','rb')
print(f.tell())
f.seek(-5,2) #2时,倒序(注意回车产生的空字节,换行时间win系统\r\n算2字节)
print(f.read())
print(f.tell())
f.seek(3,1)
print(f.tell())
读取文件最后一行
f=open('日志文件','rb')
data=f.readlines()
print(data[-1].decode('utf-8'))
f=open('日志文件','rb')
for i in f.readlines(): #会在内存中存储文件的每一行,因为读出来了
print(i)
循环文件的推荐方式
for i in f:
print(i)
for i in f:
offs=-10 #偏移量,一行中大概有多少字节
while True:
f.seek(offs,2)
data=f.readlines()
if len(data) > 1:
print('文件的最后一行是%s' %(data[-1].decode('utf-8')))
break
offs*=2
迭代器:
迭代器协议、可迭代对象、强大的for循环
递归:自己调用自己
迭代:每次循环得到的都是基于上次的
迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退)
可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个_iter_()方法,也直接可以用iter(X)表示该方法)协议是一种约定,可迭代对象实现了迭代器协议,Python的内部工具(如for循环sum,min,max函数等)使用迭代器协议访问对象
强大的for循环:
for循环机制---->循环所有对象遵循迭代器协议,取对象值---->用next方法
(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环时,可以调用他们内部的_iter_方法,把他们都变成了可迭代对象
字符串、列表:
x='hello'
# print(dir(x))
iter_test=x.__iter__()
print(iter_test)
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
l=[1,2,3]
for i in l: #i_l=l.__iter_() i_l.__next__()
print(i)
iter_l=l.__iter__() #遵循迭代器协议,生成可迭代对象
print(iter_l.__next__()) #捕捉StopIteration异常,终止迭代
print(iter_l.__next__())
index=0
while index < len(l):
print(l[index])
index+=1
字符串列表元组---->有序的可以用下标索引遍历
字典,集合等无序的---->for循环遍历
字典、集合:
s={1,2,3}
for i in s:
print(i)
iter_s=s.__iter__()
print(iter_s) #迭代器---->类似一个地址,用时才遍历
print(iter_s.__next__()) #执行一次后没保存,Python会立刻回收
print(iter_s.__next__())
print(iter_s.__next__())
print(iter_s.__next__())
dic={'a':1,'b':2}
iter_d=dic.__iter__() #字典默认取keys值
print(iter_d.__next__()) #next方法默认返回的是keys
f=open('test.txt','r+')
# for i in f:
iter_f=f.__iter__()
print(iter_f)
print(iter_f.__next__(),end='')
print(iter_f.__next__(),end='')
while循环模拟for循环调用过程
l=[1,2,3,4,5]
diedai_l=l.__iter__()
while True:
try:
print(diedai_l.__next__())
except StopIteration:
# print('迭代完毕了,循环终止了')
break
可迭代对象==迭代器
l=['die','erzi','sunzi','chongsunzi'] iter_l=l.__iter__() #可迭代对象==迭代器 print(iter_l) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(next(iter_l)) #next()---->iter_l.__next__()
for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法
迭代器就是可迭代对象
生成器:
两种生成器、生成器优点、生成器小结、三元表达式、列表解析、生成器表达式
生成器---->一种数据类型,这种数据类型自动实现了迭代器协议(不用调用_iter_方法),所以生成器就是可迭代对象
Python中有两种不同的方式提供生成器:
生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从他离开的地方继续执行
生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
生成器优点:Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处
生成器小结:
1.是可迭代对象
2.实现了延迟计算,省内存
3.生成器本质和其他的数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算省内存的好处,其余的可迭代对象可没有这点好处
def test():
yield 1
yield 2
yield 3
g=test()
print('来自函数',g)
print(g.__next__())
print(g.__next__())
三元表达式:
name='alex' name='linhaifeng' res='SB' if name == 'alex' else '帅哥' print(res) # SB一元,if name==''一元,else''一元
列表解析:
egg_list=[]
for i in range(10):
egg_list.append('鸡蛋%s' %i) #字符串拼接
print(egg_list)
l=['鸡蛋%s' %i for i in range(10)]
# l1=['鸡蛋%s' %i for i in range(10) if i > 5 ]
# # l1=['鸡蛋%s' %i for i in range(10) if i > 5 else i] #报错,没有四元表达式
# l2=['鸡蛋%s' %i for i in range(10) if i < 5] #没有四元表达式
生成器表达式:
laomuji=('鸡蛋%s' %i for i in range(10)) #生成器表达式
print(laomuji)
print(laomuji.__next__())
print(laomuji.__next__())
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
print(next(laomuji))
列表解析把[]换成()得到的就是生成器表达式
列表解析和生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
生成器表达式一次一次取值
浙公网安备 33010602011771号