【问题标题】:yielding islice from reading file从读取文件中产生 islice
【发布时间】:2017-12-12 16:53:59
【问题描述】:

希望有人可以帮助我理解以下内容。编写一个小程序以 K 行块读取 csv 文件。我已经看到了关于这个的其他堆栈问题,这不是我在这里要问的。我试图理解为什么一个程序终止而另一个程序永远不会终止。

这段代码永远不会终止:

from __future__ import print_function
from itertools import islice
import time
import csv
def gen_csv1(input_file, chunk_size=50):
    try:
        with open(input_file) as in_file:
            csv_reader = csv.reader(in_file)
            while True:
                yield islice(csv_reader, chunk_size)
    except StopIteration:
        pass

gen1 = gen_csv1('./test100.csv')

for chunk in gen1:
    print(list(chunk))
    time.sleep(1)

虽然这很好用。唯一的区别是生成器的yield 之外的islice

def gen_csv(input_file):
    try: 
        with open(input_file) as in_file:
            csv_reader = csv.reader(in_file)
            while True:
                yield next(csv_reader)
    except StopIteration:
        pass


gen = gen_csv('./test100.csv')
for chunk in gen:
    rows = islice(gen, 50)
    print(list(rows))
    time.sleep(1)

我被难住了。非常感谢任何指导。这更多是出于好奇,而不是出于工作原因。

【问题讨论】:

标签: python python-2.7 generator yield


【解决方案1】:

根据the docs

[islice] 的作用类似于列表上的 slice(),但返回一个迭代器。

当你对一个空列表进行切片时,会返回一个空列表:

In [118]: [][:3]
Out[118]: []

同样,当您islice 一个空迭代器时,将返回一个空迭代器。 相反,在空迭代器上调用 next 会引发 StopIteration

In [98]: from itertools import islice
In [114]: reader = iter([])

In [115]: list(islice(reader, 3))
Out[115]: []

In [116]: next(reader)
StopIteration: 

由于islice 永远不会引发StopIteration 异常,因此代码的第一个版本永远不会终止。

【讨论】:

  • @ubuntu - 这是否也意味着islice 没有在内部使用next
  • @mistertee:顶级 Python 文档仅指定 Python 语言的行为应该是什么。实现细节取决于 Python 的风格。可以想象,islice 可以在try..except 语句中调用next,并处理任何出现的StopIteration 异常。但在最常见的 Python 风格 CPython 中,isliceimplemented in C。它不调用next (Python) 函数;空迭代器的情况在较低级别处理。
  • @ubuntu - 再次感谢您。并感谢指向 itertools 源的链接。很有趣。
  • 对不起,我拼错了你的名字。一定是肌肉记忆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 2018-01-14
  • 2023-03-25
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多