迭代器和生成器初识

迭代器和生成器初识

1迭代器

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()---------iter()是创建迭代器。

关于迭代器的一些简单用法有:

l=[1,2,3,4]
a=iter(l)
print(next(a))
print(next(a))
print(next(a))
print(next(a))

输出:1

           2

           3

           4

l=[1,2,3,4]
a=iter(l)
for i in a:
    print(i)

输出:1

           2

           3

           4

冒出来的感觉

来源于:Python3 迭代器与生成器 | 菜鸟教程 (runoob.com)

2生成器

1解释

生成器是一种特殊的迭代器,它可以通过函数中的yield语句来实现。生成器函数在每次调用时返回一个值,并在下一次调用时从上一次离开的地方继续执行。以下是一个用代码详细解释生成器的

以下是一个用代码解释生成器和迭代器关系的例子:

```python
class MyIterator:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start < self.end:
            value = self.start
            self.start += 1
            return value
        else:
            raise StopIteration

# 创建迭代器对象
my_iter = MyIterator(1, 4)

# 通过迭代器遍历值
for value in my_iter:
    print(value)
```

在上面的例子中,我们定义了一个迭代器类`MyIterator`,它实现了`__iter__()`方法和`__next__()`方法。`__iter__()`方法返回迭代器对象本身,而`__next__()`方法定义了迭代器的行为。

我们创建了一个迭代器对象`my_iter`,并通过for循环遍历迭代器中的值。每次迭代时,for循环会自动调用迭代器对象的`__next__()`方法来获取下一个值在`__next__()`方法中,我们检查当前值是否小于结束值,如果是,则返回当前值并更新下一个值;如果不是,则引发StopIteration异常来表示迭代结束。

需要注意的是,生成器是一种特殊的迭代器,它通过yield语句来实现迭代器的功能。在上面的例子中,我们可以将迭代器类`MyIterator`改写为生成器函数,如下所示:

```python
def my_generator(start, end):
    while start < end:
        yield start   #返回start值
        start += 1

# 创建生成器对象
gen = my_generator(1, 4)

# 通过生成器遍历值
for value in gen:
    print(value)
```

这样,我们可以得到相同的结果。生成器函数`my_generator()`使用yield语句返回一系列的值,而不需要显式地实现`__iter__()`方法和`__next__()`方法。for循环会自动处理StopIteration异常,并在生成器没有更多的值可返回时退出循环。

例子:

```python
def my_generator():
    yield 1
    yield 2
    yield 3

# 创建生成器对象
gen = my_generator()

# 通过调用__next__()方法获取生成器中的值
print(gen.__next__())  # 输出: 1
print(gen.__next__())  # 输出: 2
print(gen.__next__())  # 输出: 3

# 生成器在没有更多值可返回时会引发StopIteration异常
# print(gen.__next__())  # 引发StopIteration异常
```

在上面的例子中,我们定义了一个生成器函数`my_generator()`它使用yield语句来返回一系列的值。当我们调用`my_generator()`时,它不会立即执行函数体,而是返回一个生成器对象`gen`。

在这个例子中,调用`gen.__next__()`方法是为了手动获取生成器中的值。

生成器对象是可迭代的,它可以通过for循环来遍历生成器中的值。但是,在这个例子中,我们选择手动调用`__next__()`方法来逐个获取生成器中的值。

调用`gen.__next__()`方法会使生成器函数从上一次离开的地方继续执行,直到遇到下一个yield语句。每次调用`__next__()`方法时,生成器函数会返回一个值。

在这个例子中,生成器函数`my_generator()`定义了三个yield语句,分别返回值1、2和3。通过连续调用`gen.__next__()`方法,我们可以逐个获取生成器中的值,并将其打印出来。

当生成器没有更多的值可返回时,它会引发StopIteration异常。这是因为生成器函数中的yield语句已经全部执行完毕,没有更多的值可返回。

在这个例子中,我们注释掉了最后一个`gen.__next__()`方法的调用,因此没有引发StopIteration异常。如果取消注释并运行该代码,会引发StopIteration异常,因为生成器已经没有更多的值可返回。

通常情况下,我们不需要手动调用`__next__()`方法来获取生成器中的值。我们可以使用for循环来自动遍历生成器中的值,并在生成器没有更多的值可返回时退出循环。这是因为for循环会自动处理StopIteration异常。

例如,我们可以使用for循环来遍历生成器中的值,如下所示:

```python
for value in gen:
    print(value)
```

这样,我们可以逐个获取生成器中的值,并将其打印出来。当生成器没有更多的值可返回时,for循环会自动退出循环,不会引发StopIteration异常。

因此,在大多数情况下,我们可以使用for循环来遍历生成器中的值,而不需要手动调用`__next__()`方法。只有在特殊情况下,我们才需要手动调用`__next__()`方法来逐个获取生成器中的值。

这样,我们可以依次打印出生成器中的值1、2、3。

2解释

通过使用yeild语句,可以创建并返回不止一个结果,可以返回整个结果序列的函数,这种函数被称为生成器。(生成器是一种函数)

yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

当在生成器函数中使用 yield 语句时,函数的执行将会暂停,并将 yield 后面的表达式作为当前迭代的值返回。

然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。这样,生成器函数可以逐步产生值,而不需要一次性计算并返回所有结果。

调用一个生成器函数,返回的是一个迭代器对象。

用代码例子解释如下:

def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()    #上边的foo()函数里边有yield,所以只能作为一个生成器,所以就只运行到print()
print(next(g))  #生成器中的next()函数就是接着foo()上一步没弄完的,遇见yield,返回4并停止
print("*"*20)
print(g.send(7))  #如果这个代码是print(next(g))的话,那么res就赋值为None.

#但是此处如果用send的话,开始执行的时候,先接着上一次(返回4之后)执行,先把7赋值给了res,然后执行next的作用,遇见下一回的yield,return出结果后结束。

输出:

starting...
4
********************
res: 7
4

代码引自:https://blog.csdn.net/mieleizhi0522/article/details/82142856

代码二:
 
def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b      # 使用 yield
        # print b 
        a, b = b, a + b 
        n = n + 1
 
for n in fab(5): 
    print n

输出1 



5

简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法),这样我们就可以更清楚地看到 fab 的执行流程

摘自:Python yield 使用浅析 | 菜鸟教程 (runoob.com:

3.一些运用的小例子

3.1关于for循环与生成器的运用

def foo(num):
    print("starting...")
    while num<10:
        num=num+1
        yield num
for n in foo(0):  
    print(n)

循环执行fab()内部代码,第一次循环,执行print,输出"starting...",0<10,num=1,返回num,print(n)。第二次循环继续上次yield结束那里,类似于continue,继续while循环,1<10,num=2,返回2,print(n)......

3.2关于怎样用迭代器执行求和的时间

def odd(n,m):

        while n<m:

                yield n   #sum将每个数字都装入内存。通过生成器对象反复调用_next_()特殊方法来实现的,生成器只返回None之外的值。(所以,我以后会看懂的( ̄︶ ̄))

                n+=2

sum(odd(1,100))

Thank you for reading!And welcome your advice.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值