文件处理+生成器

1.打开文件,得到文件句柄并赋值给一个变量

2.通过句柄对文件进行操作

3.关闭文件

文件操作基本流程

f = open('chenli.txt') #打开文件
first_line = f.readline()
print('first line:',first_line) #读一行
print('我是分隔线'.center(50,'-'))
data = f.read()# 读取剩下的所有内容,文件大时不要用
print(data) #打印读取内容
 
f.close() #关闭文件

文件打开模式

打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。

打开文件的模式有:

  • r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
  • w,只写模式【不可读;不存在则创建;存在则清空内容】
  • x, 只写模式【不可读;不存在则创建,存在则报错】
  • a, 追加模式【可读;   不存在则创建;存在则只追加内容】

"+" 表示可以同时读写某个文件

  • r+, 读写【可读,可写】
  • w+,写读【可读,可写】
  • x+ ,写读【可读,可写】
  • a+, 写读【可读,可写】

 "b"表示以字节的方式操作

  • rb  或 r+b
  • wb 或 w+b
  • xb 或 w+b
  • ab 或 a+b

 注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

文件内置函数flush

flush原理:

  1. 文件操作是通过软件将文件从硬盘读到内存
  2. 写入文件的操作也都是存入内存缓冲区buffer(内存速度快于硬盘,如果写入文件的数据都从内存刷到硬盘,内存与硬盘的速度延迟会被无限放大,效率变低,所以要刷到硬盘的数据我们统一往内存的一小块空间即buffer中放,一段时间后操作系统会将buffer中数据一次性刷到硬盘)
  3. flush即,强制将写入的数据刷到硬盘

滚动条:

import sys,time

for i in  range(10):
    sys.stdout.write('#')
    sys.stdout.flush()
    time.sleep(0.2)

文件内光标移动

注意:read(3)代表读取3个字符,其余的文件内光标移动都是以字节为单位如seek,tell,read,truncate

整理中

open函数详解

open(file[, mode[, buffering[, encoding[, errors[, newline[, closefd=True]]]]]])
open函数有很多的参数,常用的是file,mode和encoding
file文件位置,需要加引号
mode文件打开模式,见下面3
buffering的可取值有0,1,>1三个,0代表buffer关闭(只适用于二进制模式),1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小;
encoding表示的是返回的数据采用何种编码,一般采用utf8或者gbk;
errors的取值一般有strict,ignore,当取strict的时候,字符编码出现问题的时候,会报错,当取ignore的时候,编码出现问题,程序会忽略而过,继续执行下面的程序。
newline可以取的值有None, \n, \r, ”, ‘\r\n',用于区分换行符,但是这个参数只对文本模式有效;
closefd的取值,是与传入的文件参数有关,默认情况下为True,传入的file参数为文件的文件名,取值为False的时候,file只能是文件描述符,什么是文件描述符,就是一个非负整数,在Unix内核的系统中,打开一个文件,便会返回一个文件描述符。

2. Python中file()与open()区别
两者都能够打开文件,对文件进行操作,也具有相似的用法和参数,但是,这两种文件打开方式有本质的区别,file为文件类,用file()来打开文件,相当于这是在构造文件类,而用open()打开文件,是用python的内建函数来操作,建议使用open

3. 参数mode的基本取值

Character Meaning
‘r' open for reading (default)
‘w' open for writing, truncating the file first
‘a' open for writing, appending to the end of the file if it exists
‘b' binary mode
‘t' text mode (default)
‘+' open a disk file for updating (reading and writing)
‘U' universal newline mode (for backwards compatibility; should not be used in new code)

r、w、a为打开文件的基本模式,对应着只读、只写、追加模式;
b、t、+、U这四个字符,与以上的文件打开模式组合使用,二进制模式,文本模式,读写模式、通用换行符,根据实际情况组合使用、

常见的mode取值组合

 1 r或rt 默认模式,文本模式读
 2 rb   二进制文件
 3     
 4 w或wt 文本模式写,打开前文件存储被清空
 5 wb  二进制写,文件存储同样被清空
 6     
 7 a  追加模式,只能写在文件末尾
 8 a+ 可读写模式,写只能写在文件末尾
 9     
10 w+ 可读写,与a+的区别是要清空文件内容
11 r+ 可读写,与a+的区别是可以写到文件任何位置 

----------------------------------------------------------------------------------------

f = open("p.py","r",encoding="utf-8")
读文件以utf8形式
f = open("p.py","rb")
如果加b不能指定编码
data = f.read
print(data.decode("utf-8"))

f = open("test22.py","w")
f.write直接写 会把原来文件覆盖
f = open("test22.py""wb")
f.write(bytes("1111",encoding = "utf-8"))
f.write("1111".encode("utf-8"))
f = open("test22.py""ab") 写在文件的最后位置 加\n换行

 ----------------------------------------------------------------------------------------

迭代器:

1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退)

2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法)

3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。

 

(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环式,调用了他们内部的__iter__方法,把他们变成了可迭代对象

然后for循环调用可迭代对象的__next__方法去取值,而且for循环会捕捉StopIteration异常,以终止迭代

1 l=['a','b','c']
 2 #一:下标访问方式
 3 print(l[0])
 4 print(l[1])
 5 print(l[2])
 6 # print(l[3])#超出边界报错:IndexError
 7 
 8 #二:遵循迭代器协议访问方式
 9 diedai_l=l.__iter__()
10 print(diedai_l.__next__())
11 print(diedai_l.__next__())
12 print(diedai_l.__next__())
13 # print(diedai_l.__next__())#超出边界报错:StopIteration
14 
15 #三:for循环访问方式
16 #for循环l本质就是遵循迭代器协议的访问方式,先调用diedai_l=l.__iter__()方法,或者直接diedai_l=iter(l),然后依次执行diedai_l.next(),直到for循环捕捉到StopIteration终止循环
  #for循环所有对象的本质都是一样的原理
17 
18 for i in l:#diedai_l=l.__iter__()
19     print(i) #i=diedai_l.next()
20 
21 #四:用while去模拟for循环做的事情
22 diedai_l=l.__iter__()
23 while True:
24     try:
25         print(diedai_l.__next__())
26     except StopIteration:
27         print('迭代完毕了,循环终止了')
28         break

生成器:

可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

 

def lay_eggs(num):
    egg_list=[]
    for egg in range(num):
        egg_list.append('蛋%s' %egg)
    return egg_list

yikuangdan=lay_eggs(10) #我们拿到的是蛋
print(yikuangdan)


def lay_eggs(num):
    for egg in range(num):
        res='蛋%s' %egg
        yield res
        print('下完一个蛋')

laomuji=lay_eggs(10)#我们拿到的是一只母鸡
print(laomuji)
print(laomuji.__next__())
print(laomuji.__next__())
print(laomuji.__next__())
egg_l=list(laomuji)
print(egg_l)
#演示只能往后不能往前
#演示蛋下完了,母鸡就死了

三元运算:

#三元表达式
name='tom'
name='jerry'
res='cat' if name == 'tom' else 'haozi'
print(res)

生成器表达式和列表解析

egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析
laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
print(laomuji)
print(next(laomuji)) #next本质就是调用__next__
print(laomuji.__next__())
print(next(laomuji))

总结:

1.把列表解析的[]换成()得到的就是生成器表达式

2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议

posted @ 2016-12-07 22:30  JasonEnbo  阅读(452)  评论(0编辑  收藏  举报