【问题标题】:Does the builtin open() return a generator?内置 open() 是否返回生成器?
【发布时间】:2020-11-02 13:36:19
【问题描述】:

这是关于“发电机”使用的正确术语的问题。我们看一下内置函数open()返回的文件对象。

1。内置open()函数,官方文档

official python documentation 中,然后open() 函数据说返回一个“文件对象”,而documentation for file object 并没有真正说明这是什么生物,除了它有read()write()方法和那个

文件对象也称为类文件对象或流。

????‍♂️ 这很有帮助,对吧?

2。网上的话

这里有一些例子,其中open() 返回的文件对象被称为生成器。

2.1。 How to Use Generators and yield in Python (Realpython.com)

(强调我的)

open() 返回一个 generator 对象,您可以懒惰地逐行迭代

2.2. Lazy Method for Reading Big File in Python?

(接受 400+ 分的答案,强调我的)

如果文件是基于行的,则文件对象已经是一个惰性生成器 行数:

for line in open('really_big_file.dat'):
    process_data(line)

2.3。 Generators in Python — 5 Things to Know (medium.com)

(强调我的)

使用open()方法打开EEG文件会创建一个文件 对象,它作为一个 generator 产生一行数据作为 每次都是字符串。

人们可能很容易从 Internet 上的任何地方找到更多此类示例。

3。测试open() 返回的文件对象是否为生成器

按照How to check if an object is a generator object in python?,我们可以对文件对象进行一些测试:

In [7]: o = open(r'C:\tmp\test.csv')

In [8]: type(o)
Out[8]: _io.TextIOWrapper

In [9]: import inspect

In [10]: inspect.isgenerator(o)
Out[10]: False

In [12]: inspect.isgeneratorfunction(o)
Out[12]: False

In [13]: import types

In [14]: isinstance(o, types.GeneratorType)
Out[14]: False

所有这些测试都失败了,暗示open() 返回的文件对象不是生成器。尽管如此,很多人还是倾向于称它为生成器。

4。包括或不包括发电机?

那么,python 爱好者们,open() 函数返回一个生成器是否正确?并执行以下操作

for line in open('file.csv'):
    do_something(line)

涉及使用生成器?

【问题讨论】:

  • 既然你可以seek一个打开的文件:显然不行。
  • __next____next__ 方法的source code 表示TextIoWrapperTextIoBase 的子类,IOBase 的子类。 also says 表示“IOBase 对象可以迭代 yielding 流中的行。”。他们在那里使用术语“产量”。使用for line in open(file) 读取行时会说涉及到一些生成器吗?
  • 在该段落中,它明确使用了 iterator 这个词,而不是生成器。 “yield”这个词很可能是在英语意义上使用的,而不是在 Python 关键字意义上。
  • 你也可以这样做:l = [1, 2, 3] ; for num in l: ... 这不会使列表成为生成器,它是一个可迭代。就像文件对象一样。您可以使用它像生成器一样表现,但区别如上所述,您可以seek 返回文件。你不能倒带发电机
  • 有道理。我检查了TextIOWrapper 的源代码,似乎除了是一个可迭代对象之外,它还是一个 iterator (它具有返回self__iter__ 方法)。

标签: python


【解决方案1】:

python open 函数返回一个不是生成器的TextIOWrapper 对象。

您可以遍历对象的原因是因为它定义了__next__ 方法。 你可以找到它的源代码here,它会帮助你弄清楚事情。

【讨论】:

  • 谢谢!请参阅我对这个问题的评论;提到“IOBase 对象可以迭代 *yielding *流中的行。”。这会说使用for line in open(file): ..时涉及到一个生成器吗?
  • @np8 我将源代码与我的答案相关联,IOBase 类没有定义__next__ 方法。文档中的 yield 一词是指 IOBase 类的子类,并不意味着涉及到生成器。
  • open的直接返回类型是TextIOWrapper,它不是生成器。
猜你喜欢
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 2017-12-29
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多