文件处理的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\n',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)) #[]