博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python-生成器
阅读量:4653 次
发布时间:2019-06-09

本文共 3998 字,大约阅读时间需要 13 分钟。

1.列表生成式

需求:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 要求你把列表里的每个值加1

方式一:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> for index,i in enumerate(a):...     a[index] += 1...>>> a[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

方式二:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]a = list(map(lambda x:x+1, a))print(a)# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

方式三: 列表生成式

>>> a = [i+1 for i in range(10)]>>> a[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>>>

2.python生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

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

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个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(10))>>> g
at 0x000000000261B258>

创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

我们可以打印generator 中的每个元素 ,next(g)

>>> next(g)0>>> next(g)1>>> next(g)4>>> next(g)9>>> next(g)16>>> next(g)25>>> next(g)36>>> next(g)49>>> next(g)64>>> next(g)81>>> next(g)Traceback (most recent call last):  File "
", line 1, in
StopIteration

generator 保存的是算法,每次调用next(g)计算并返回每个元素值,,直到最后一个元素后再next(g),会报StopIteration 的错;

因为generator是可迭代对象,所以我们可以使用 for 循环来处理:

>>> g = (x*x for x in range(10))>>> for i in g:...     print(i)...0149162536496481>>>

我们可以看到,for循环 g 不会在最后报错


其实,range() 就是一个生成器

>>> range(1000000000)range(0, 1000000000)>>>

range(1000000000) 后,并没有打印出生成的列表,而是生成了一个公式算法,并没有生成这个列表,在我们真正使用的时候才会不断生成,当然这是在python3 中。

在python2中,range(10) 后,会把列表直接打印出来,但是python2.7中有一个 xrange(10) ,和python3中的 range()是一样的


用函数写一个生成器

#斐波那契数列def fib(max):    n, a, b = 0, 0, 1    while n < max:        print(b, end=" ")        a, b = b, a + b        n += 1    return 'done'fib(10) # 1 1 2 3 5 8 13 21 34 55

改动一下,把print改为yield

def fib(max):    n, a, b = 0, 0, 1    while n < max:        print("bofore yield......")        yield b        print("after yield.......")        a, b = b, a + b        n += 1    return 'done'f = fib(10)  # turn fuction into a generator# 无打印结果,未执行
next(f)  # bofore yield......

next(f)一下,

next(f)next(f)

打印结果:

# bofore yield......# after yield.......# bofore yield......

注意:

  • yield b ,把函数的执行过程冻结在这一步,并且把b的值 返回到外面的 next(f),这里可以把函数里面每一步的值返回出来,这一点很有用,在一些场景中可以利用
  • 函数只要加 yidld,函数就会冻结,不再执行,然后生成一个生成器对象

def range2(n):    count = 0    while count < n:        print('count:',count)        count += 1        yield count #    print('------')    return 'end........'new_range = range2(3)n1 = next(new_range)n2 = next(new_range)n3 = next(new_range)n4 = next(new_range)print(n3)print(n4)

打印结果:

Traceback (most recent call last):  File "D:/Python/python_learning/luffy/code/part2/函数/生成器4.py", line 18, in 
n4 = next(new_range)StopIteration: end........count: 0count: 1count: 2------

注意:只要函数中有 yield ,

1.函数名加() 就得到了一个生成器,

2.return在生成器中,代表生成器的终止,

3.在运行到最后的时候,就会报出异常,此时,return的内容会以 StopIteration: end........ 的异常方式反馈


def range2(n):    count = 0    while count < n:        print('count:',count)        count += 1        # yield count        sign_str = yield count        print('sign_str:',sign_str)    print('------')    return 'end........'new_range = range2(3)n1 = next(new_range)print("do someting else...")new_range.send("stop")

打印:

count: 0do someting else...sign_str: stopcount: 1

1.send,唤醒并继续执行

2.发送一个信息到生成器内部

我们可以根据send到生成器内部的内容做一些事情,比如:

def range2(n):    count = 0    while count < n:        print('count:',count)        count += 1        # yield count        sign_str = yield count        if sign_str == 'stop':            break    return 'end........'new_range = range2(3)n1 = next(new_range)print("do someting else...")new_range.send("stop")

打印:

Traceback (most recent call last):  File "D:/Python/python_learning/luffy/code/part2/函数/生成器6.py", line 19, in 
new_range.send("stop")StopIteration: end........count: 0do someting else...

newt(new_range) 实际上是发了一个 'None' 到生成器内部

转载于:https://www.cnblogs.com/friday69/p/9246483.html

你可能感兴趣的文章
ConcurrentHashMap实现原理及源码分析
查看>>
PowerDesigner 中将Comment(注释)及Name(名称)内容互相COPY的VBS代码
查看>>
浅谈WPF的VisualBrush
查看>>
经常用得到的安卓数据库基类
查看>>
vue element 关闭当前tab 跳转到上一路由
查看>>
4、面向对象
查看>>
[NOI2005]聪聪与可可(期望dp)
查看>>
POJ 3723
查看>>
Elgg网站迁移指南
查看>>
Sublime Text 3 及Package Control 安装(附上一个3103可用的Key)
查看>>
基于uFUN开发板的心率计(一)DMA方式获取传感器数据
查看>>
【dp】船
查看>>
oracle, group by, having, where
查看>>
⑥python模块初识、pyc和PyCodeObject
查看>>
nodejs pm2使用
查看>>
CSS选择器总结
查看>>
mysql中sql语句
查看>>
sql语句的各种模糊查询语句
查看>>
Python20-Day05
查看>>
C#操作OFFICE一(EXCEL)
查看>>