代码之家  ›  专栏  ›  技术社区  ›  lo tolmencre

为什么在下一个生成器中使用yield会返回生成器?[副本]

  •  0
  • lo tolmencre  · 技术社区  · 6 年前

    我在用 yield 返回 __next__() 在我的班上。但是它不返回下一个值,而是返回生成器对象。

    我试图更好地理解迭代器和 产量 . 我可能做错了。

    看一看。

    class MyString:
        def __init__(self,s):
            self.s=s
    
        def __iter__(self):
            return self
    
        def __next__(self):
            for i in range(len(self.s)):
                yield(self.s[i])
    
    r=MyString("abc")
    i=iter(r)
    print(next(i))
    

    这将返回:

    generator object __next__ at 0x032C05A0

    0 回复  |  直到 5 年前
        1
  •  10
  •   mgilson    9 年前

    next 差不多只是打电话 __next__() 在这种情况下。打电话 __next__ 在对象上启动生成器并返回它(此时不执行任何魔法)。


    在这种情况下,你 可以 能够逃脱不确定 __下一个__ 完全:

    class MyString:
        def __init__(self,s):
            self.s=s
    
        def __iter__(self):
            for i in range(len(self.s)):
                yield(self.s[i])
            # Or...
            # for item in self.s:
            #     yield item
    

    如果你想用 __iter__ __下一个__ (定义 iterator 而不是简单地 iterable ),你可能会想这样做:

    class MyString:
        def __init__(self,s):
            self.s = s
            self._ix = None
    
        def __iter__(self):
            return self
    
        def __next__(self):
            if self._ix is None:
                self._ix = 0
    
            try:
                item = self.s[self._ix]
            except IndexError:
                # Possibly reset `self._ix`?
                raise StopIteration
            self._ix += 1
            return item
    
        2
  •  6
  •   Aran-Fey Kevin    6 年前

    让我们看看 __next__ 方法。从 the docs :

    迭代器

    从容器中返回下一个项目。如果没有其他项,则引发StopIteration异常。

    现在让我们看看 yield 是的。另一段摘自 the docs :

    在函数体中使用yield表达式会导致该函数 做发电机

    以及

    当调用生成器函数时,它返回一个名为 发电机。

    现在比较一下 __下一个__ 产量 : __下一个__ 返回容器中的下一项 . 但是包含 产量 关键字 返回迭代器 . 因此,使用 产量 在一个 __下一个__ 方法生成生成迭代器的迭代器。


    如果你想用 为了使你的班级适合你,在 __iter__ 方法:

    class MyString:
        def __init__(self, s):
            self.s = s
    
        def __iter__(self):
            for s in self.s:
                yield s
    

    这个 __iter__ 方法应该返回一个迭代器- 产量 keyword让它做到了这一点。


    为了完整起见,下面是如何使用 __下一个__ 方法。您必须跟踪迭代的状态,并返回相应的值。最简单的解决方案可能是每次都增加一个索引 __下一个__ 被称为:

    class MyString:
        def __init__(self,s):
            self.s = s
            self.index = -1
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self.index += 1
    
            if self.index >= len(self.s):
                raise StopIteration
    
            return self.s[self.index]