Python 为什么从内部生成的下一个对象返回生成器对象?

Python 为什么从内部生成的下一个对象返回生成器对象?,python,generator,next,Python,Generator,Next,我正在使用yield在类中的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()函数中返回下一个值。但是,它不会返回下一个值,而是返回生成器对象 我正在努力更好地理解迭代器和yield。我可能做得不对 看一看 class MyString: def __init__(self,s): self.s=s def __iter__(self): return self def

我正在使用
yield
在类中的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()函数中返回下一个值。但是,它不会返回下一个值,而是返回生成器对象

我正在努力更好地理解迭代器和
yield
。我可能做得不对

看一看

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))
这将返回:


在这种情况下,0x032C05A0处的
生成器对象\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在对象上调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,将启动生成器并返回它(此时不执行任何魔术)


在这种情况下,您可能完全不需要定义
\uuuuuuuuuuuuuuuuuuuuuuuuuu

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
如果您想使用
\uuuu iter\uuuuu
\uuuuu next\uuuuuuu
(定义一个而不是简单地制作一个),您可能需要执行以下操作:

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

让我们看看
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。发件人:

迭代器。下一个

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

现在让我们看看
yield
语句的作用。另一段摘录自:

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

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

现在比较
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是包含
yield
关键字的函数返回迭代器。因此,在
\uuuuuuuuuuuuuu
方法中使用
yield
,将生成生成迭代器的迭代器


如果您想使用
yield
使您的类更易理解,请使用以下方法:

\uu iter\uu
方法应该返回一个迭代器,而
yield
关键字正好让它返回迭代器


为了完整起见,下面是如何使用
\uuuuuuuuuuuuuuuuuuuu
方法实现迭代器。您必须跟踪迭代的状态,并返回相应的值。最简单的解决方案可能是每次调用
\uuu next\uuu
时增加索引:

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]

据我所知,生成器函数只是带有next函数的类的语法糖。例如:

>>> def f():
    i = 0
    while True:
        i += 1
        yield i


>>> x = f()
>>> x
<generator object f at 0x0000000000659938>
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> class g(object):
    def __init__(self):
        self.i = 0

    def __next__(self):
        self.i += 1
        return self.i


>>> y = g()
>>> y
<__main__.g object at 0x000000000345D908>
>>> next(y)
1
>>> next(y)
2
>>> next(y)
3

这可能是实现我认为您正在寻找的目标的最简单的方法。

因此,将
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>作为生成器并不真正有意义,或者这意味着
MyString
迭代器的每个值都是生成器。MyString不应该定义
\uu<代码>\uuuuuuuuuuuuuuuuuu下一步\uuuuuuuuu
用于迭代器,而不是iterables。类似地,它不应该
\uuuu iter\uuuu
返回self
。我没有看到最近的编辑。我在问为什么会这样missing@MosesKoledoye--是的,这是我在你发表评论时纠正的原始帖子中的一个疏忽。我还意识到调用
iter(mystring)
可能不应该重置迭代。。。谢谢你看着我的背。:-)您是否不需要在
def\uuuu iter\uuuu(self)
上执行
self.index=-1
来重置迭代,然后,当稍后调用或嵌套为
以用于in列表时。。。对于列表中的b。。。如果一个=b、 ..
@user嗯,作为自身迭代器的对象通常不会在
\uu iter\uu
方法中重置。例如,考虑一个文件对象。您只能在上面迭代一次。
>>> def f():
    i = 0
    while True:
        i += 1
        yield i


>>> x = f()
>>> x
<generator object f at 0x0000000000659938>
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> class g(object):
    def __init__(self):
        self.i = 0

    def __next__(self):
        self.i += 1
        return self.i


>>> y = g()
>>> y
<__main__.g object at 0x000000000345D908>
>>> next(y)
1
>>> next(y)
2
>>> next(y)
3
class MyString:
    def __init__(self,s):
        self.s=s
        self._i = -1

    def __iter__(self):
        return self

    def __next__(self):
        self._i += 1
        if self._i >= len(self.s):
            raise StopIteration
        return self.s[self._i]