参考:生成器

Note

1.通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的,且容易造成空间浪费。所以,如果列表元素可以按照某种算法推算出来,那我们可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间,在Python中这种机制称为生成器:generator。

注意:generator保存的是算法。

第一种生成generator的方法很简单,将列表生成式的[]括号改为()即可:

#!/usr/bin/env python3

L = [i*i for i in range(1, 11)]

G = (i*i for i in range(1, 11))

print(L)

print(G)
sh-3.2# ./generator1.py
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
<generator object <genexpr> at 0x101be17d8>

如果想要一个一个打印出来generator的元素,可以借助next()函数来访问。

>>> g = (i*i for i in range(1, 11))

>>> 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)
100
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

generator保存的是算法,在调用next()函数的时候是先用保存的算法计算得到值再输出。next()函数在越界的时候报“StopIteration”错误。

但是= =,generator基本不用next()函数。一般使用for循环输出元素。

for i in G :
print(i)
1
4
9
16
25
36
49
64
81
100

2.generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如斐波那契数列:

def fib(maxn) :
i, a, b = 1, 1, 1
print(1)
while i < maxn:
print(b)
a, b = b, a+b
i = i+1

输出斐波那契数列的前n个数。

>>> from generator1 import fib

>>> fib(5)
1
1
2
3
5 >>> fib(10)
1
1
2
3
5
8
13
21
34
55

注意语句:i, a, b = 1, 1, 1

仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,这种算法也可以通过generator的方法进行保存。

改动为generator也很简单:print(b) => yield(b)。

def fib1(maxn) :
i, a, b = 0, 0, 1
while i < maxn:
yield(b)
a, b = b, a+b
i = i+1
>>> from generator1 import fib1
>>> fib1(5)
<generator object fib1 at 0x101be18e0>
>>> fib1(10)
<generator object fib1 at 0x101be1938>

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

注意理解这段话:

  • 1.generator在使用next()的时候基于保存的算法进行计算并执行语句;
  • 2.generator在遇到yield(n)语句的时候返回n;
  • 3.再次用next()调用generator时,从上一个返回的yield语句开始执行。
def exp():
print('step 1:')
yield(1) print('step 2:')
yield(3) print('step 3:')
yield(5)

exp()函数内含yield()语句,因而是一个generator。

>>> from generator1 import exp
>>> exp()
<generator object exp at 0x1013e1938>

调用exp()函数时,需要先创建一个generator对象,并通过next()函数执行generator。

>>> output = exp()

>>> print(next(output))
step 1:
1 >>> print(next(output))
step 2:
3 >>> print(next(output))
step 3:
5 >>> print(next(output))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

因此,generator在调用next()函数时执行,在遇见yield()语句时返回。

当然,我们在函数也尽量避免使用next()函数,使用迭代取代next。

>>> for i in fib1(5):
... print(i)
...
1
1
2
3
5

练习:

杨辉三角定义如下:

          1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

把每一行看做一个list,试写一个generator,不断输出下一行的list:

My Answer:

def triangles():
i = 1
L = []
while i <= 10:
L1 = []
L1.append(1) if i > 1 :
for j in range(1, i-1):
# print('i', i, 'j', j)
a, b = int(L[j]), int(L[j-1])
# print(a, b)
L1.append(a+b) if i > 1 :
L1.append(1) yield(L1)
i = i+1
L = L1 n = 0 for t in triangles():
print(t)
n = n + 1
if n == 10:
break
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
sh-3.2#

2017/2/7

最新文章

  1. WorkFlowHelper
  2. [NHibernate]利用LINQPad查看NHibernate生成SQL语句
  3. Cocoapods的安装
  4. centos6.5为tengine安装php 5.6支持
  5. Trilateration三边测量定位算法
  6. Dynamic CRM 2013学习笔记(四十一)流程4 - 异步工作流(Workflow)用法图解
  7. Python之配置文件模块 ConfigParser
  8. JS判断鼠标从什么方向进入一个容器
  9. POJ 3253 Fence Repair【二叉堆】
  10. POJ 2352 Stars
  11. android81 多线程下载和断电续传
  12. AndroidStudio 更新gradle Error:Failed to complete Gradle execution. Cause: Connection reset
  13. 如何获取App当前版本号
  14. [poj 1265]Area[Pick定理][三角剖分]
  15. catalan卡特兰数
  16. webpack code splitting
  17. Python爬虫入门教程 1-100 CentOS环境安装
  18. Xcode9模拟器隐藏边框
  19. web实验博客3.css-position
  20. Java8 Hash改进/内存改进

热门文章

  1. python学习笔记(二)— 字符串(string)
  2. 转!mysql备份与还原数据库
  3. 爬虫之cookiejar模块
  4. (2.7)Mysql之SQL基础——表的操作与查看
  5. uib-datepicker-popup 日期不可输入 只可以选择 :readonly=&quot;true&quot;
  6. ambari rest api (修改集群配置文件)
  7. Java网络通信基础编程
  8. vue项目中多个入口的配置
  9. Teleport Ultra 垃圾代码 tppabs的清理&lt;转&gt;
  10. 手机端1px细线公共类