【问题标题】:python modify mutable iteratorpython修改可变迭代器
【发布时间】:2018-09-13 04:52:25
【问题描述】:

代码如下:

f=open('test.txt')
file=iter(f)

当我这样做时

next(file)

它将逐行打印文件。 但是当我修改了test.txt文件并保存后,next(file) 还是打印了原来的文件内容。

迭代器是否将完整的文件存储在内存中? 如果不是,为什么文件的内容没有更新?

【问题讨论】:

  • 不,文件迭代器不会将文件内容存储在内存中。它将位置存储在文件中。该文件通常由块加载,因此它存储一个缓冲区(默认为 8192 字节,但可能会有所不同)。
  • 顺便说一句,f 对象本身是一个带有 f.next 方法的迭代器(以及 Python 3.+ 中的 f.__next__)..你不需要明确地传递它 iter(...) 函数跨度>
  • 所以如果我的文件大小大于 8192 字节缓冲区大小,那么理论上如果我修改文件的最后一行,结果将是新内容而不是原始内容?

标签: python iterator generator


【解决方案1】:

不,作为迭代器,file 对象在内存中仅存储一个前瞻缓冲区,而不是完整的文件。这使得它对大文件很有效。

由于有这个前瞻缓冲区,对文件所做的更改不会反映到next 方法。但是,您可以使用seek 方法清除此缓冲区,以便下次调用next 方法将返回更新后的内容:

f.seek(f.tell()) # seek the current position only to clear the look-ahead buffer
print(next(f)) # prints the updated next line from the current position

【讨论】:

  • 是的,这也是我所知道的。但如果是这样,为什么修改物理文件内容不影响下一行?
  • 我已经用解释和解决方案更新了我的答案。
  • 所以如果我的文件大小大于 8192 字节缓冲区大小,那么理论上如果我修改文件的最后一行,结果将是新内容而不是原始内容?
  • 是的,就是这样。
【解决方案2】:

假设open() 一次读取 2 个字母。 (实际值为io.DEFAULT_BUFFER_SIZE

f=open('test.txt')

您已经创建了一个文件对象 _io.TextIOWrapper,它过于简单化了,就像 [{read from 0 to io.DEFAULT_BUFFER_SIZE of test.txt}, ...}

file=iter(f)

您已经创建了 _io.TextIOWrapper 的迭代器,其数据如下:[{read from 0 to 1}, ... {read from n-1 to n}]

next(file)

next() 浏览了file 的第一项,阅读并打印。

让我们从一个例子中学习。

正常阅读

test.txt

what a beautiful day

我们将打开文件,iter() 和 list() 打开并遍历所有文件并创建一个列表。

In [1]: f = open('test.txt')

In [2]: list(iter(f))
Out[2]: ['what a beautiful day']

正如预期的那样。

open() 之后的文件更改

In [1]: f = open('test.txt')

我们已经打开了文件。

我们现在将 hello open() 附加到 test.txt。

test.txt

what a beautiful day

hello open()

然后是 iter() 和 list() 它。

In [2]: list(iter(f))
Out[2]: ['what a beautiful day\n', '\n', 'hello open()']

可以看到更改的内容。我们可以看到open()实际上并没有读取文件。

iter() 之后的文件更改

In [1]: f = open('test.txt')

In [2]: i = iter(f)

我们已经打开了文件和iter()d。

我们现在将追加hello iter()

test.txt

what a beautiful day

hello open()

hello iter()

然后列出()它。

In [3]: list(i)
Out[3]: ['what a beautiful day\n', '\n', 'hello open()\n', '\n', 'hello iter()']

可以看到更改的内容。我们还可以看到iter()实际上并没有读取文件。

【讨论】:

    猜你喜欢
    • 2011-03-02
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多