Python迭代器与生成器

Python迭代器与生成器

迭代器

迭代器是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器的两个基本方法:iter()next()
字符串、列表或元组对象都可用于创建迭代器。
文件不需要创建迭代器,文件本身就是迭代器。
迭代器对象不要求事先准备好整个迭代过程中的所有元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或者之后,元素可以不存在或者被销毁。

>>> list = [1,2,3,4]
>>> list_iter = iter(list)
>>> list_iter.next()
1
>>> list_iter.next()
2
>>> list_iter.next()
3
>>> list_iter.next()
4

当list没有next之后,抛出StopIteration异常。

>>> list_iter.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

生成器

生成器是一种特殊的迭代器。生成器一定是迭代器,迭代器不一定是生成器。
它不需要再像上面的类一样写__iter__()__next__()方法了,只需要一个yiled关键字。
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。

# coding=utf-8
from __future__ import print_function
import sys
def fibonacci(n):  # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n):
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10)  # f 是一个迭代器,由生成器返回生成
print (f)
while True:
    try:
        print (next(f), end=" ")
    except StopIteration: #抛出异常
        sys.exit()

运行结果

<generator object fibonacci at 0x00000000030511F8>
0 1 1 2 3 5 8 13 21 34 55 

问: 将列表生成式中[]改成() 之后数据结构是否改变?
答案:是,从列表变为生成器
通过列表生成式,可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。
此外,如果创建一个包含百万元素的列表,不仅是占用很大的内存空间,如:我们只需要访问前面的几个元素,后面大部分元素所占的空间都是浪费的。因此,没有必要创建完整的列表(节省大量内存空间)。
在Python中,可以采用生成器:边循环,边计算的机制—>generator。

>>> list = [i for i in range(5)]
>>> list
[0, 1, 2, 3, 4]
>>> type(list)
<type 'list'>
>>> generator = (i for i in range(5))
>>> generator
<generator object <genexpr> at 0x0000000003583240>
>>> type(generator)
<type 'generator'>

生成器示例代码

示例01

# -*- coding: utf-8 -*-
import sys
def out_money(totle):
    while totle > 0:
        totle -= 1
        yield 1                             # yield 返回一个值
ATM = out_money(3)   #ATM generator中的值为:1 1 1,即如果存在next,next(ATM)=1
while True:
    try:
        print("取到钱 %s 万" % next(ATM))
        print("花掉花掉!")
    except StopIteration:
        print ("没钱了")
        sys.exit()

运行结果

取到钱 1 万
花掉花掉!
取到钱 1 万
花掉花掉!
取到钱 1 万
花掉花掉!
没钱了

示例02

# coding=utf-8
import time

def consumer(name):
    print("%s 准备吃包子了!" %name)
    while True:
        baozi = yield                    # yield 通过 send()方法接收值
        print("包子[%s]来了,被[%s]吃了" %(baozi,name))

def producer(name):
    c1 = consumer('A')
    c2 = consumer('B')
    c3 = consumer('C')
    next(c1)
    next(c2)
    next(c3)

    print("%s 开始准备做包子了!" % name)

    for i in range(5):
        time.sleep(1)
        print('做了3个包子')
        c1.send(i)
        c2.send(i)
        c3.send(i)

producer('hh')

运行结果

A 准备吃包子了!
B 准备吃包子了!
C 准备吃包子了!
hh 开始准备做包子了!
做了3个包子
包子[0]来了,被[A]吃了
包子[0]来了,被[B]吃了
包子[0]来了,被[C]吃了
做了3个包子
包子[1]来了,被[A]吃了
包子[1]来了,被[B]吃了
包子[1]来了,被[C]吃了
做了3个包子
包子[2]来了,被[A]吃了
包子[2]来了,被[B]吃了
包子[2]来了,被[C]吃了
做了3个包子
包子[3]来了,被[A]吃了
包子[3]来了,被[B]吃了
包子[3]来了,被[C]吃了
做了3个包子
包子[4]来了,被[A]吃了
包子[4]来了,被[B]吃了
包子[4]来了,被[C]吃了
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值