【问题标题】:How To Make a Generator, That's Composed of Another Generator如何制作一个由另一个发电机组成的发电机
【发布时间】:2017-07-21 14:38:01
【问题描述】:

我想做一个发电机。并且该生成器应该采用可迭代的。这基本上是为了让我可以将生成器插入现有框架。

这是我目前得到的代码。

class Iter1(object):

    def __init__(self, iterable=None):
        self.iterable = iterable

    def __iter__(self):
        if self.iterable is None:
            self.iterable = Iter2()
        return self.iterable

    def next(self):
        for thing in self.iterable:
            yield thing


class Iter2(object):

    DEFAULT_PATH = r"/Users/Documents/stuff.txt"

    def __init__(self, path=None):
        self.path = path or self.DEFAULT_PATH

    def __iter__(self):
        return self

    def next(self):
        with open(self.path, 'r') as f:
            for line in f:
                yield line


if __name__ == "__main__":
    iterable = Iter1()
    for thing in iterable:
        print(thing)

这段代码有两个问题。首先是返回(产生)的不是文件中的一行,而是另一个生成器对象。 第二个是它不返回文件中的行数,它只返回无限多的行。我明白这是因为每次我在Iter2 中调用next 时,我都会再次打开文件,但是我不明白如何在不将整个文件加载到内存的情况下生成每一行。

【问题讨论】:

    标签: python python-2.7 iterator generator


    【解决方案1】:

    PEP 234 -- Iterators:

    任何一种形式的 iter() 返回的迭代器对象都有一个 next() 方法。此方法要么返回下一个值 迭代,或引发 StopIteration (或派生的异常类) 表示迭代结束。任何其他例外都应该是 被认为表示错误并应正常传播, 不表示迭代的结束。

    您正在从next() 返回一个迭代器,这就是它没有按预期工作的原因。相反,您应该在每次调用 next() 时返回一个值。

    另外,让__iter__() 返回self 有点奇怪。通常假设多次调用iter(sequence) 将返回多个新迭代器,每个迭代器都从序列的开头开始,但您的代码并非如此。

    【讨论】:

    • 你说的有道理,但我不太明白代码中的问题出在哪里。 iter2 中的 next 方法应该从文件中产生一行,不是吗?这应该意味着Iter1next 方法也产生了一行,不是吗?
    • @GreeTreePython 不,在next() 中使用yield 是不对的。在这种情况下,您的迭代器包装器可以执行以下操作:def next(self): return next(self.iterator)。 Python 本身会重复调用你的next() 方法,并且每次都会返回一个值,或者当没有更多值时抛出一个StopException。由于您包装的迭代器具有相同的next 行为,您可以直接转发它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2021-12-13
    • 2021-12-11
    • 2017-06-10
    相关资源
    最近更新 更多