文件处理的b模式,b模式 打开的是二进制
f=open('test11.py','rb',encoding='utf-8') #b的方式不能指定编码 f=open('test11.py','rb') #b的方式不能指定编码 data=f.read() #'字符串'---------encode---------》bytes #bytes---------decode---------》'字符串' print(data) print(data.decode('utf-8')) f.close()
f=open('test22.py','wb') #b的方式不能指定编码 f.write(bytes('1111 ',encoding='utf-8')) #方法一 f.write('杨件'.encode('utf-8')) #方法二
文件操作的其他方法
文件r模式的话是根据系统的编码
f=open('a.txt','r+',encoding='utf-8') data=f.read() print(f.encoding) #utf-8 f.write('你好') #一个文件只能有一种格式
f=open('a.txt','r',encoding='utf-8',newline='') #读取文件中真正的换行符号 print(f.closed) print(f.encoding) #打印字符编码 f.flush() #刷新 保存数据 print(f.readlines())
f=open('a.txt','r',encoding='utf-8',newline='') #读取文件中真正的换行符号 print(f.closed) print(f.encoding) #打印字符编码 print(f.tell()) #0 文件当前位置 f.readline() print(f.tell()) #6 文件当前位置
f.flush() #讲文件内容从内存刷到硬盘 f.closed #文件如果关闭则返回True f.encoding #查看使用open打开文件的编码 f.tell() #查看文件处理当前的光标位置 f.seek(3) #从开头开始算,将光标移动到第三个字节 f.truncate(10) #从开头开始算,将文件只保留从0-10个字节的内容,文件必须以写方式打开,但是w和w+除外
迭代器与生成器
迭代器
迭代
更新换代
迭代器协议:
迭代器协议是指:对象必须提供一个next方法, 执行该方法要返回迭代中的下一项。要么就引起一个StopIteration异常,以终止迭代(只能往前不能往后)
for循环的本质:循环所有对象,全都使用迭代器协议
只要有__iter__方法 就可以把他们变成可迭代对象,然后for循环调用对象的__next__()方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代
next() #是内置函数
next() ---> #调用迭代器的__next__()方法
迭代器就是可迭代对象,他们是一回事。只要遵循迭代器协议,生成的数据类型就是可迭代对象
可迭代对象:
只要遵循迭代器协议,生成的数据类型就是可迭代对象
iter_l=l.__iter__() #遵循迭代器协议,生成可迭代对象 print(iter_l.__next__()) print(iter_l.__next__())
for i in s: print(i) iter_s=s.__iter__() print(iter_s) print(iter_s.__next__()) print(iter_s.__next__()) print(iter_s.__next__()) print(iter_s.__next__())
dic={'a':1,'b':2} iter_d=dic.__iter__() print(iter_d.__next__()) #a
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__()
生成器
什么是生成器?
可以理解为一种数据类型。这种数据类型自动的实现了迭代器协议(其他的数据类型需要调用自己的__iter__方法),所以生成器是可迭代对象
python提供了2中的不同的方式生成器
1.生成器函数:常规函数定义,但是,使用yield语句而不是使用return语句返回结果。yield语句返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行
def test(): yield 1 yield 2 yield 3 g=test() print('来自函数',g) #来自函数 <generator object test at 0x0000000002382A98> print(g.__next__()) #1 print(g.__next__()) #2 print(next(g)) #3
2.生成器表达式: 类似于列表推导。但是,生成器返回按需产生结果的一个对象。而不是一次构建一个结果列表
#列表解析 egg_list=[] for i in range(5): egg_list.append('鸡蛋%s' %i) print(egg_list) #['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4'] l=['鸡蛋%s' %i for i in range(5)] print(l) #['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4'] l1=['鸡蛋%s' %i for i in range(5) if i > 3 ] print(l1) #['鸡蛋4'] # l1=['鸡蛋%s' %i for i in range(5) if i > 3 else i] #没有四元表达式 l2=['鸡蛋%s' %i for i in range(5) if i < 3] #没有四元表达式 print (l2) #['鸡蛋0', '鸡蛋1', '鸡蛋2']
laomuji=('鸡蛋%s' %i for i in range(10)) #生成器表达式 () 省内存 print(laomuji) #<generator object <genexpr> at 0x0000000002552A98> print(laomuji.__next__()) print(next(laomuji)) #next() 本质就是调用__next__ print(next(laomuji)) #鸡蛋1 print(next(laomuji)) #鸡蛋2
生成器小结:
1.是可迭代的对象
2.实现了延迟机选,省内存
3.生成器的本质和其他数据类型一样,都是实现了迭代器协议,只不过生成器附加了一个延迟计算内存的好处。其余的可迭代对象没有这个好处
4.生成器只能遍历一次, 取完就为空
t = range(3) t1=(i for i in t) t2=(i for i in t1) print(list(t1)) #[0, 1, 2] print(list(t2)) #[]