Python生成器(generator)和迭代器(Iterator)

列表生成式

a = [i+1 for i in range(10)]
print(a)

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

这就是列表生成式

生成器(generator)

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。

如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的    list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(generator)。

# 列表生成式:
L = [x * x for x in range(10)]
print(L)
# 生成器:
g = (x * x for x in range(10))
print(g)

输出结果:

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x00000267824C0258>

list可以直接打印出结果,但是generator只能通过next()获得下一个返回值

g = (x * x for x in range(4))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

输出结果:

0
1
4
9

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

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

生成器示例:

def fib(max_n):                            # 斐波那契数列生成器
    n, a, b = 0, 0, 1
    while n < max_n:
        yield b                            # 函数中出现yield则函数变成生成器
        a, b = b, a+b
        n = n+1
    return "done"

f = fib(6)
print(f.__next__())                        # 生成器生成一个数(f.__next__()=next(f))
print("______")                            # 生成器无法返回,之后生成的数据不包含以上的数

while True:
    try:
        x = next(f)                        # 循环生成数列
        print("f:", x)                     # 输出计算结果
    except StopIteration as e:             # 当循环次数大于max_n时,运行以下
        print("Generator return value:", e.value)
        break

输出结果:

1
______
f: 1
f: 2
f: 3
f: 5
f: 8

当函数中出现 ‘yield’ 时这个函数就成了一个 generator 的函数

generator在执行的时候遇到 yield 时会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

通过yield实现在单线程的情况下实现并发运算的效果:

import time

def consumer(name):
    print("%s开始吃包子了" % name)
    while True:
        produce = yield                                # 函数在此暂停,等待唤醒
        print("%s吃了%i个包子" % (name, produce+1))      # 唤醒后执行

def producer(name):
    c = consumer("A")
    c2 = consumer("B")
    c.__next__()
    c2.__next__()
    print("%s准备开始生产" % name)
    for i in range(3):
        time.sleep(1)
        print("已经做了%i个包子" % (i+1))
        c.send(i)                                       # 将i发送给produce,并唤醒函数
        c2.send(i)

producer("C")

输出结果:

A开始吃包子了
B开始吃包子了
C准备开始生产
已经做了1个包子
A吃了1个包子
B吃了1个包子
已经做了2个包子
A吃了2个包子
B吃了2个包子
已经做了3个包子
A吃了3个包子
B吃了3个包子

在 producer 函数中 c 和 c2 轮流调用 consumer 函数

send() 和 next() 一样可以唤醒生成器,而且还能给 yield 传值

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

  • 一类是集合数据类型,如list、tuple、dict、set、str等;
  • 一类是generator,包括生成器和带 yield 的 generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator.

生成器都是Iterator对象,但list、dict、str 虽然是 Iterable ,却不是Iterator。
把list、dict、str 等 Iterable 变成Iterator可以使用 iter() 函数.

 

 

原文地址:https://www.cnblogs.com/dbf-/p/10574741.html

时间: 2024-10-07 11:33:13

Python生成器(generator)和迭代器(Iterator)的相关文章

生成器generator和迭代器Iterator

一.列表生成式       在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2,3,4,5]可以使用list(range(6)),但是如果想要生成[,,,,,]即[0,1,4,9,16,25]怎么做? #方法一:循环>>> L = []>>> for x in range(6):... L.append(x**2)...>>> L[

Python之生成器(generator)和迭代器(Iterator)

generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,可以使用next()函数和send()函数恢复生成器. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用.但是,不同于一般函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这个消耗的内存数量将大大减小.因此,生成器看起来像是一个函数,但是表现得像迭代

【25】Python生成器generator

列表生成式一个小题目:将里列表[0,1,2,3]里面的数值都加1.方法1: a=[0,1,2,3] b=[] for i in range(len(a)): b.append(i+1) a=b print(a) 方法2: a = [1,3,4,6,7,7,8] for index,i in enumerate(a): a[index] +=1 print(a) 方法3: a=[0,1,2,3,4] a=map(lambda x:x+1,a) print(a) for i in a: print(

python生成器 Generator

生成器 Generator 什么是生成器? 生成器是能够动态提供数据的可迭代对象 生成器在程序运行时生成数据,与容器类不同,它通常不会在内存中保存大量的数据,而是现用现生成 生成器有两种: 生成器函数 生成器表达式 生成器函数 含有yield语句的函数是生成器函数,此函数被调用将返回一个生成器对象 注: yield翻译为(产生或生成) yield 语句 语法: yield 表达式 说明: yield 用于 def函数中,目的是将此函数作用生成器函数使用yield 用来生成数据,供迭代器的next

Python 生成器generator

列表的问题列表生成器可以直接创建一个表,但是,如果一个表中有100万个元素,那么这个表太占空间,而且往往我们仅仅需要访问前面几个元素,后面绝大多数元素占用的空间都白白浪费了. 生成器如果列表元素可以按照某种算法推算出来,那我们可以在循环的过程中不断的推算出后续的元素.而不用一开始就创建整个list.这样,节省了大量的空间.这种一遍循环一遍计算的机制,称为生成器:generator. 创建生成器generator.第一种方法:只要报一个列表生成式的[]改成(),就穿件了一个generator.创建

python 生成器 generator

一.生成器定义 通过列表生成表达式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间.在Python中,这种一边循环一边计算的机制,称为生成器:generator. 1 >>> l = [x * x for x in range(10)] 2 >>> l 3 [0, 1, 4, 9, 16, 25, 36,

python学习--生成器Generator

生成器函数:在函数中如果出现了yield关键字,那么这个函数就是生成器函数,yield的作用就是生成一个generator,生成器函数返回一个生成器. 实现一个generator:1.把列表的[ ]换成(),就创建了一个generator. >>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range

ES6中的迭代器(Iterator)和生成器(Generator)

前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 本文将详细介

ES6中的迭代器(Iterator)和生成器(Generator)(一)

用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 一.引入 下面是一段标

Python 生成器&迭代器

Python 生成器 带有 yield 的函数在 Python 中被称之为 generator(生成器),用斐波那契数列: def fab(max):     n, a, b = 0, 0, 1     while n < max:         yield b         a, b = b, a + b         n = n + 1 执行: 1 2 3 4 5 6 7 8 9 >>> for n in fab(5):     print n 1 1 2 3 5 简单地