Python 文件迭代器(2)

来源:互联网 发布:网络是否应该受管制 编辑:程序博客网 时间:2024/06/10 18:30

上一篇博文(也就是我的第一篇博文)讲了Python文件迭代器的属性。

那篇博文讲到,在Python中,迭代器是文件对象的内秉属性,而迭代器用法 for line in File 会改变File对象的迭代器属性,这个属性不因退出循环而被还原。


今天在使用Python处理一个小文件的过程中发现,file.read()和file.readlines()这两个命令同样会对file对象的迭代器属性产生影响,从而给迭代器用法带来不利的影响。


同样用foo.txt文件为例,它的文件内容是:

line1  line2  line3  line4  line5  line6  line7  line8  line9 

执行以下代码:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        for line in file:        print line

其输出为:

line1line2line3line4line5line6line7line8line9请按任意键继续. . .

这里,文件迭代器能够正常工作。

当在文件迭代器前增加file.read()语句后,即执行以下代码:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        file.readlines()        for line in file:        print line
其输出结果为:

请按任意键继续. . .

输出仅为一个空行。这说明file.readlines()的确影响了file内秉的迭代器属性,使得 for line in file用法出错。

为了进一步验证这个想法,在file.readlines()后添加seek()语句,如下:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        file.readlines()        file.seek(-32,1)        for line in file:        print line
输出结果为:

line6line7line8line9请按任意键继续. . .


可以看出,此时迭代器会按照seek()设定的值往后进行迭代。

通过以上实验可以看出,file.readlines()命令的确会影响迭代器的属性。那么,迭代器会反过来影响file.read()吗?答案是是的。

首先看执行如下代码:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        for line in file:        print line        print file.readlines()
输出结果为:

line1line2line3line4line5line6line7line8line9[]请按任意键继续. . .

可以看到,当迭代器循环结束后,file.readlines()输出结果为空列表[];而重新定位文件偏移后,file.reaklines()又可以重新从定位位置开始输出。

那么,seek()的文件定位,与迭代器的文件定位,带来的效果是一样的吗?我为了解决这个疑惑,进行了下面的实验:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        i = 0    for line in file:        i = i + 1        if i ==5:            break        print line        print file.readlines()
输出结果为:

line1line2line3line4Traceback (most recent call last):  File "C:\Users\tsinghua\Desktop\test.py", line 17, in <module>    print file.readlines()ValueError: Mixing iteration and read methods would lose data请按任意键继续. . .

竟然报错了!

接下来,我在迭代器后面添加了seek()语句,如下:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        i = 0    for line in file:        i = i + 1        print line        if i ==5:            break                file.seek(-16,1)    print file.readlines()
输出结果为:

line1line2line3line4line5['\n', 'line8  \n', 'line9']请按任意键继续. . .

若从seek()语句的功能出发,上面这个输出结果表明,在强行中断迭代循环后,file对象的当前位置被定位在了file末尾。那么,此时迭代器定位也是文件末尾吗?我接下来执行了如下命令:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        i = 0    for line in file:        i = i + 1        print line        if i ==5:            break            print file.next()        file.seek(-16,1)    print file.readlines()
输出结果为:

line1line2line3line4line5line6['\n', 'line8  \n', 'line9']请按任意键继续. . .

结果表明,此时迭代器定位在了强行终止迭代的地方,而seek()所寻找的file对象的当前位置依然是在file末尾。


接下来,我又进行了两个对比实验:

# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        print file.next()        print file.readlines()
输出结果为:
line1Traceback (most recent call last):  File "C:\Users\tsinghua\Desktop\test.py", line 12, in <module>    print file.readlines()ValueError: Mixing iteration and read methods would lose data请按任意键继续. . .


# coding = gbk# program name: FileIterator2import sysimport osos.chdir(sys.path[0])with open('foo.txt','r') as file:        print file.next()        file.seek(-16,1)    print file.readlines()
输出结果为:

line1['\n', 'line8  \n', 'line9']请按任意键继续. . .


一套测试下来,我目前变得更加疑惑了。目前可以确定的几点有:

1. seek()命令有关的文件当前位置与文件迭代器的位置不是一码事;

2.文件迭代器的执行与file.readlines()\file.read()命令的执行都会影响文件当前位置以及文件迭代器位置;

3. file.readlines()命令的执行会直接使文件迭代器定位到结束为止;文件迭代器命令的全部执行会使得文件当前位置定位到文件末尾;文件迭代器命令的部分执行会导致file.readlines()命令报错。

至于具体原理是什么,我还没搞清楚,希望有大神前来解答。

0 0
原创粉丝点击