Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于生成器编写python迭代器的最佳方法是什么_Python_Iterator_Generator - Fatal编程技术网

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

基于生成器编写python迭代器的最佳方法是什么,python,iterator,generator,Python,Iterator,Generator,我一直在寻找一种编写基于生成器的Python迭代器的好方法。我已经找到了很多关于迭代器的教程,还有很多关于生成器和yield语句的教程,但是没有找到将两者结合在一起的教程。我已经建立了一个小的例子,并想知道是否有更好的方法来做到这一点 class myIterator : def __init__(self, n) : self.last = n self.myGen = self.myGenerator() def __iter__(sel

我一直在寻找一种编写基于生成器的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
类My迭代器:
定义初始化(self,n):
self.last=n
self.myGen=self.myGenerator()
定义(自我):
返回self.myGenerator()
def next(自我):
返回self.myGen.next()
def myGenerator(自):
prev=0
fib=1
当fib
我在一个真实世界的程序中使用了这种技术,可以在

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

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

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

迭代器协议由两部分组成。
\uuuu iter\uuuu
方法是最重要的方法,当您在对象上使用
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
或者可以重用生成器的
.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
类My迭代器:
定义初始化(self,n):
self.last=n
self.next=self.myGenerator().next#使用生成器`.next`
定义(自我):
回归自我
def myGenerator(自):
prev=0
fib=1
当fib
生成器已经是迭代器了。无需对其进行包装:

>>> 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
>>def gen():
...  收益率1
...  收益率2
...  收益率3
... 
>>> 
>>>a=gen()
>>>处长(a)
“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU u'、uu str_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
>>>ai=a.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
>>>哎
>>>a
>>>a.下一步()
1.
>>>a.下一步()
2.
>>>a.下一步()
3.
>>>a.下一步()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
停止迭代

为什么不返回
self.myGen
?谢谢。这可能行得通,但它仍然涉及到我希望避免的混乱。谢谢你,这正是我所希望的。注意,在Python3中,迭代器需要一个
\uuuuuuuuuuuuuuuuuuuuu
方法(而不仅仅是
next
)和
iterator。next()
不再受支持(应该使用
next(迭代器)
)。第一个示例提供了基于生成器的迭代器,但不包括next()功能。在第一个例子中,
\uu iter\uu
本身就是生成器,生成器提供自己的
.next()
方法<代码>\uuuu iter\uuuu
应该返回迭代器,而生成器符合该要求。在第二种形式中,我们返回
self
,然后才需要显式定义
.next()
方法。这正是我所希望的,但当我尝试使用next()时,它告诉我“myIterator实例没有属性'next'”。实际上,在现实世界中,有理由将其包装到类中。当我开始这个项目时,我使用了一个生成器,它变得有点混乱,所以我决定使用一个类来包装它的其他部分。我将再次尝试“仅生成器”方法thanksWell,如果您认为需要包装生成器,您可能需要告诉我们更多关于您的用例的信息。用例将文件解析为SQL语句。有相当多的设置,我肯定需要使用yield,因为结果是从for循环的中间返回的。但我将再次尝试仅使用生成器的版本谢谢
>>> 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