当我从__next__里面屈服的时候.为什么它会返回生成器对象?

sac*_*hin 10 python generator next

我使用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))
Run Code Online (Sandbox Code Playgroud)

返回:

生成器对象__next__位于0x032C05A0

mgi*_*son 10

next__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
Run Code Online (Sandbox Code Playgroud)

如果你想使用__iter____next__(来定义迭代器而不是简单地进行迭代),你可能想要做这样的事情:

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
Run Code Online (Sandbox Code Playgroud)


Ara*_*Fey 6

我们来看看该__next__方法的目的.来自文档:

迭代器.__下__()

从容器中返回下一个项目.如果没有其他项,请提高StopIteration异常.

现在让我们看看该yield声明的作用.文档的另一部分摘录:

在函数体中使用yield表达式会导致该函数成为生成器

当调用生成器函数时,它返回一个称为生成器的迭代器.

现在比较__next__yield:__next__ 返回容器中的下一个项目.但是包含yield关键字的函数会返回迭代器.因此,yield__next__方法中使用会产生一个产生迭代器的迭代器.


如果要使用yield可迭代的类,请在__iter__方法中执行:

class MyString:
    def __init__(self, s):
        self.s = s

    def __iter__(self):
        for s in self.s:
            yield s
Run Code Online (Sandbox Code Playgroud)

__iter__方法应该返回一个迭代器 - yield关键字使它完全相同.


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

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]
Run Code Online (Sandbox Code Playgroud)