今日所学:
一、文件处理b模式
f=open("text.py","rb")--->读出的为二进制形式 data=f.read() print(data) f.close() f=open("text.py","r",encoding="utf-8")--->可读出文件内容 data=f.read() print(data) f.close()
注意:在使用b模式时(rb,wb,ab),不能再指定编码,本身就是以二进制方式进行读
f=open("text.py","wb") f.write("sdfksdjgksjdh\n")--->报错 在进行写的操作时,需把写进的内容转化成二进制的方式,用bytes()函数,注意编码 1、f=open("text.py","wb") f.write(bytes("fasdffgf\n",encoding="utf-8"))--->用bytes()将写入的内容转化为二进制 2、f=open("text.py","wb") f.write("kjshfks\n".encode("utf-8"))--->直接写入,并调用.encode()编码utf-8
二、文件的其他内置函数
1、f.tell()返回光标的所在位置,位于读操作的后面,先读取一行,接着可用tell获得此时光标的位置
f=open("text.py","rb") data=f.readline() print(data) print(f.tell()) f.close()
注意:
1、当文本形式为.txt时,加上newline=""(内部为空),可把真正的换行符显示出来
2、在不同操作系统中的换行符不同 --> inux:\n windows:\r\n mac:\r
f=open("tell","r",encoding="utf-8",newline="") print(f.readline()) print(f.tell())--->读的时候光标的位置还算上Windows系统中的换行符\r\n(占两个字节) f.close()
2、f.seek()是用来移动光标的位置,是位于读操作的前面。
f=open("tell","r",encoding="utf-8",newline="") f.seek(12,0)--->当有汉字时,光标的移动是以字节为单位的,所以移动需以字节方式进行参数赋值,字母则不用。 data=f.read() print(data) f.close()
注意:汉字在utf8编码下占3个字节,gbk下占2个字节,而英文不管在那个编码下都只占1个字节!
f=open("tell","rb") f.seek(6,0)--->0和默认就是从文件最开头往后找,光标向后移 data=f.readline() print(data) print(f.tell()) f.seek(3,1)--->1代表从当前位置往后再找,光标向后移。这种在打开文件时需以b模式打开 print(f.readline()) print(f.tell()) f.seek(-12,2)--->2代表倒着找,光标向前移 print(f.readline()) print(f.tell()) f.close()
3、for循环:用readlines的话会先把这个文件用列表的形式保存在内存中,再读取出来,这样会比较占内存。
所以用for循环可直接把文件里面的内容循环打印出来。
f=open("tell","r+",encoding="utf-8") for i in f: print(i,end="")
4、truncate截取,文件不能以w+打开,因为这样就给清空了,截取不了。在截取时是从开头开始,且截取后悔覆盖原文件。
f=open("tell","r+",encoding="utf-8") print(f.truncate(25)) f.close()
注意:文件不能以w的方式打开,而r和a都可以。
三、迭代器和生成器
1、迭代和递归
(1)迭代:是一个重复的过程,每次重复就是一次迭代,并且每次迭代的结果都是下一次迭代的初始值。
l=[1,3,5,6] count=0 while count < len(l): print(l[count]) count+=1
>>>
1
3
5
6
(2)递归:是在一个函数的最后一步调用另一个函数
2、迭代器
(1)迭代器协议:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个stopiteration异常,以终止迭代(只能往后走不能往前走)。
(2)迭代器对象:实现了迭代器协议的对象。即内置有_iter_方法的对象(字符串、列表、元祖、字典、集合、文件)
‘hello‘.__iter__ (1,2,3).__iter__ [1,2,3].__iter__ {‘a‘:1}.__iter__ {‘a‘,‘b‘}.__iter__ open(‘a.txt‘).__iter__
for循环、max、min、sum等函数都是用迭代器协议在工作。
3、for循环
序列类型:字符串、列表、元祖(都有下标,可以while循环)
非序列类型:字典、集合、文件对象
l=[1, 3, 5, 7, 8] for i in l: print(i)
上下等价操作。
l=[1,3,5,7,9]
iter_l=l.__iter__() --->先把序列转换成可迭代对象 print(iter_l.__next__()) --->调用其下的一个_next_方法,把对象一个个循环出来,若循环完毕则会报出stopiteration print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__()) print(iter_l.__next__())
总结:for循环相当于做了两件事
(1)把所有的数据类型先用_iter_函数转化为可迭代对象,并调用其下的_next_函数把元素一个个循环出来;
(2)自动识别出stopiteration,捕捉异常,并终止程序,把之前的元素输出。
所以,for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法。
4、生成器:只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
(1)生成器函数:常规函数的定义,用yield语句来代替return语句。
def trxt(): yield 1 yield 2 yield 3 print(trxt()) >>><generator object trxt at 0x0000013C109787B0> --->生成器地址
yield作用:
1、把函数做成迭代器
2、对比return,可以返回多次值,可以挂起/保存函数的运行状态
(2)生成器表达式:
a.三元表达式(if和else的另一种写法)
name=‘happy‘ if name == "happy": print("hello") else: print("bye")
>>>hello name="happy" res="helli" if name == "hppy" else "byebye" print(res)
>>>byebye
b.列表解析
1、普通的创建列表 egg_list=[] for i in range(1,10): egg_list.append("鸡蛋%d"%i) print(egg_list)
>>>[‘鸡蛋1‘, ‘鸡蛋2‘, ‘鸡蛋3‘, ‘鸡蛋4‘, ‘鸡蛋5‘, ‘鸡蛋6‘, ‘鸡蛋7‘, ‘鸡蛋8‘, ‘鸡蛋9‘]
2、列表解析 l=["鸡蛋%d"%i for i in range(1,10)] print(l)
>>>[‘鸡蛋1‘, ‘鸡蛋2‘, ‘鸡蛋3‘, ‘鸡蛋4‘, ‘鸡蛋5‘, ‘鸡蛋6‘, ‘鸡蛋7‘, ‘鸡蛋8‘, ‘鸡蛋9‘]
c.生成器表达式(把列表解析中的中括号改为小括号)
l=("鸡蛋%d"%i for i in range(1,10)) --->生成器就是迭代器 print(l) print(l.__next__()) --->迭代器下调用_next_函数 print(l.__next__()) print(l.__next__()) print(l.__next__())
补充:sum函数内部也是遵循迭代器协议(可用生成器表达器的方式赋值给sum)max、min、reduce等都是类似。
print(sum( i for i in range(178))) >>>15753
以上。
原文:https://www.cnblogs.com/211293dlam/p/12487477.html