基于gen编写python迭代器的最佳方法是什么

2024-10-02 22:26:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在寻找一种好方法来编写基于生成器的Python迭代器。我找到了很多关于迭代器主题的教程,也有很多关于生成器和yield语句的教程,但是没有找到将两者结合起来的教程。我已经建立了一个很好的例子,想知道是否有更好的方法来实现这一点。在

class myIterator :

    def __init__(self, n) :
        self.last = n
        self.myGen = self.myGenerator() 

    def __iter__(self) :
        return self.myGenerator()

    def next(self) :
        return self.myGen.next()

    def myGenerator(self) :
        prev = 0
        fib = 1
        while fib < self.last :
            res = fib
            yield res
            fib = fib + prev
            prev = res

        raise StopIteration

我在一个实际的程序中使用了这种技术,可以在SQLStatements.py in my Github repository找到它

其中最令人费解的部分是定义next()函数。显而易见的解决方案每次被调用时都返回第一个元素。存储包含生成器的实例变量是可行的,但似乎是一种浪费。在

如果你知道一个更好的方法来做这个或一个好的教程,涵盖这个主题,请让我知道。在

编辑: @MartijnPieters发布的第三个例子完全解决了这个问题。保存self.generator.next函数自我。下一个提供下一个函数。我希望这能帮助其他人解决这个问题。在


Tags: 方法函数self主题defres教程例子
2条回答

迭代器协议由两部分组成。__iter__方法是最重要的方法,当您在一个对象上使用iter()时,它应该返回迭代器。在

只需将__iter__的主体替换为myGenerator;无需提升StopIteration

class myIterator:
    def __init__(self, n):
        self.last = n

    def __iter__(self):
        prev = 0
        fib = 1
        while fib < self.last:
            res = fib
            yield res
            fib += prev
            prev = res

现在iter(myIterator(10))是一个迭代器,有一个.next()方法。在

如果您希望您的类直接用作迭代器,则需要__iter__来返回self,并提供一个.next()方法。在

一个.next()方法为每个函数体生成一个元素(并使用return somevalue)。生成器只是一个使用yield的函数,实际上,这样的方法本身为您实现了迭代器协议(包括.next())。在

如果要使用.next(),它看起来应该是这样的:

^{pr2}$

您可以重用生成器的.next()方法:

class myIterator:
    def __init__(self, n):
        self.last = n
        self.next = self.myGenerator().next  # Use the generator `.next`

    def __iter__(self):
        return self

    def myGenerator(self):
        prev = 0
        fib = 1
        while fib < self.last:
            res = fib
            yield res
            fib += prev
            prev = res

生成器已经是一个迭代器。无需包装:

>>> def gen():
...  yield 1
...  yield 2
...  yield 3
... 
>>> 
>>> a = gen()
>>> dir(a)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw']
>>> ai = a.__iter__()
>>> ai
<generator object gen at 0x542f2d4>
>>> a
<generator object gen at 0x542f2d4>
>>> a.next()
1
>>> a.next()
2
>>> a.next()
3
>>> a.next()
Traceback (most recent call last):
  File "<string>", line 1, in <module>
StopIteration

相关问题 更多 >