python迭代器、生成器及其之间

python迭代器、生成器及其之间,python,iterator,generator,Python,Iterator,Generator,所以我得到了惰性求值和生成器表达式的生成器函数,也就是生成器理解,作为它的语法等价物 我理解这样的课程 class Itertest1: def __init__(self): self.count = 0 self.max_repeats = 100 def __iter__(self): print("in __inter__()") return self def __next__(self):

所以我得到了惰性求值和生成器表达式的生成器函数,也就是生成器理解,作为它的语法等价物

我理解这样的课程

class Itertest1:
    def __init__(self):
        self.count = 0
        self.max_repeats = 100

    def __iter__(self):
        print("in __inter__()")
        return self

    def __next__(self):
        if self.count >= self.max_repeats:
            raise StopIteration
        self.count += 1
        print(self.count)
        return self.count
作为实现迭代器接口的一种方式,即在同一个类中实现iter和next

但那又是什么呢

class Itertest2:
    def __init__(self):
        self.data = list(range(100))

    def __iter__(self):
        print("in __inter__()")
        for i, dp in enumerate(self.data):
            print("idx:", i)
            yield dp
在iter成员函数中,哪个使用收益率语句

我还注意到,在调用iter成员函数时

it = Itertest2().__iter__()
batch = it.__next__()
打印语句仅在第一次调用next()时执行。
这是因为产量和iter的混合作用吗?我认为这是非常违反直觉的…

在任何函数中的任何位置使用
yield
语句将函数代码包装在(本机)生成器对象中,并用一个存根替换函数,该存根为您提供所述生成器对象

因此,在这里,调用
\uuuu iter\uuu
将为您提供一个匿名生成器对象,该对象将执行您想要的代码

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu下一个\uuuuuuuuuuu
的主要用例是提供一种不依赖(本机)生成器编写迭代器的方法

\uuuu iter\uuuu
的用例是区分对象和所述对象上的迭代状态。考虑类似

的代码
c = some_iterable()
for a in c:
    for b in c:
        # do something with a and b
您不希望这两个交错的迭代相互干扰对方的状态。这就是为什么这样的循环会去糖化为

c = some_iterable()
_iter1 = iter(c)
try:
    while True:
        a = next(_iter1)
        _iter2 = iter(c)
        try:
            while True:
                b = next(_iter2)
                # do something with a and b
        except StopIteration:
            pass
 except StopIteration:
     pass

通常,自定义迭代器实现一个存根
\uuuu iter\uuuu
,该存根返回
self
,因此
iter(iter(x))
相当于
iter(x)
。这在编写迭代器包装时非常重要。

可以使用单独的迭代器类编写与
Itertest2
等效的内容

class Itertest3:
    def __init__(self):
        self.data = list(range(100))

    def __iter__(self):
        return Itertest3Iterator(self.data)


class Itertest3Iterator:
    def __init__(self, data):
        self.data = enumerate(data)

    def __iter__(self):
        return self

    def __next__(self):
        print("in __inter__()")
        i, dp = next(self.state)  # Let StopIteration exception propagate
        print("idx:", i)
        return dp
将其与
Itertest1
进行比较,其中
Itertest1
的实例本身携带迭代的状态。每次调用
Itertest1.\uuu iter\uuuu
都返回相同的对象(Itertest1的实例),因此它们无法独立地迭代数据


请注意,我将
打印(“in uuu iter_uuu()”
放在
\uuu next\uuuu
中,而不是
\uuuu iter
。正如您所观察到的,直到第一次调用
\uuuuuuunext\uuuuuuu
,生成器函数中才真正执行任何操作。生成器函数本身只创建一个生成器;它实际上不会开始执行其中的代码。

在generator中,值是惰性计算的,即仅在需要时才计算值。(1)您应该以不同的方式命名这两个类,至少是Itertest1和Itertest2。(2) Itertest2是一个iterable,它在其
方法中创建新的独立迭代器。生成器函数返回这样一个迭代器。Itertest1是一个迭代器,按照惯例,它以
\uuuuuuuuuuuuuuuu
的形式返回自身。例如。Java更清楚地区分了iterable和iterator,但不太舒服。谢谢,但是为什么“\uuuu inter\uuuuuuuuu()”只在第一次下一次调用之后才打印,而不是调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuiiiiiuiuiuiuiui。事情是,
yield
旨在简化编写迭代器的过程(除其他外),在幕后发生了很多事情。因此,在定义
\uuuu iter\uuuuu
\uuuu next\uuuuuu
时,您没有所需的控制级别;您将它们挤压在一起,并使用
屈服