Python学习札记(十八) 高级特性4 生成器
参考:生成器
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
Python学习札记(十八) 高级特性4 生成器的更多相关文章
- Python学习札记(十五) 高级特性1 切片
参考: 高级特性 切片 Note 1.掌握了Python的基础语法之后,就可以写出很多很有用的程序了,比如打印1-90的奇数: #!/usr/bin/env python3 L = [] n = 1 ...
- Python学习札记(十九) 高级特性5 迭代器
参考:迭代器 Note 1.可用于for循环的对象有两类:(1)集合数据类型:list tuple dict str set (2)Generator:生成器和含yield语句的函数.这些可以直接作用 ...
- Python学习札记(十六) 高级特性2 迭代
参考:迭代 Note 1.如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在C.C++.Java等语言中,for循 ...
- Python学习二十八周(vue.js)
一.指令 1.一个例子简单实用vue: 下载vue.js(这里实用1.0.21版本) 编写html代码: <!DOCTYPE html> <html lang="en&qu ...
- Python学习第十八篇——低耦合函数设计思想
import json 2 def greet_user(filename): 3 try: 4 with open(filename) as f_obj: 5 username = json.loa ...
- Python学习日记(十八) 序列化模块
什么是序列? 就是每一个元素被有序的排成一列 什么是序列化? 就是将原本的列表.字典等内容转化成字符串的过程 什么时候会用到序列化? 数据存储(把数据放在文件.数据库),网络传输等 序列化的目的 1. ...
- python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制
django Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...
- Python学习札记(十二) Function3 函数参数一
参考:函数参数 Note 1.Python的函数定义非常简单,但灵活度却非常大.除了正常定义的必选参数外,还可以使用默认参数.可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以 ...
- Python学习札记(十) Function1 函数调用
参考:调用函数 Note 1.Python内置了很多函数,我们可以直接对这些函数进行调用.Python官网:Built in Fuctions eg.调用abs函数(取绝对值函数): >> ...
随机推荐
- 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活--hdu2191(多重背包模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2191 标准的多重背包 题目 有N种物品和一个容量为V的背包.第i种物品最多有n[i]件可用,每件费用是 ...
- 使用Standford coreNLP进行中文命名实体识别
因为工作需要,调研了一下Stanford coreNLP的命名实体识别功能. Stanford CoreNLP是一个比较厉害的自然语言处理工具,很多模型都是基于深度学习方法训练得到的. 先附上其官网链 ...
- 使用paramiko的SFTP get或put整个目录
在<使用paramiko执行远程linux主机命令>中举例说明了执行远程linux主机命令的方法,其实paramiko还支持SFTP传输文件. 由于get或put方法每次只能传输一个文件, ...
- flatpickr功能强大的日期时间选择器插件
flatpickr日期时间选择器支持移动手机,提供多种内置的主题效果,并且提供对中文的支持.它的特点还有: 使用SVG作为界面的图标. 兼容jQuery. 支持对各种日期格式的解析. 轻量级,高性能, ...
- data.table进阶
上一篇讲述了data.table数据分析的一些基本方法,但是最近在用作数据分析时,发现在面对一些复杂场景时,这些基本的用法已经不能满足业务需求了,所以此篇就介绍data.table更进一步的用法. 先 ...
- CentOS 6下OpenCV的安装与配置
自己按照网上的教程一步一步来的 http://www.jb51.net/os/RedHat/280309.html 虚拟机环境 CentOS 6.5 内核版本:4.1.14 64位 gcc,gcc 4 ...
- (转)C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
程序在内存有五个存在区域: A:动态区域中的栈区 B:动态区域中的栈区 C:静态区域中:全局变量 和静态变量 (这个区域又可以进一步细分为:初始化的全局变量和静态变量 以及 未初始 ...
- linux rm指定的文件
如何删除一个目录下的除了想要的文件之外的所有文件 rm `ls | grep -v "aa"` Linux下 报错“命令参数列表过长”,在用mv命令一次移动3万多个文件时失败了,原 ...
- Python 新手常犯错误(第一部分)转载
觉得这篇文章针对python的默认参数写的不错,翻译的也不错,故转载下. 原文链接: Amir Rachum 翻译: 伯乐在线- 伯乐在线读者译文链接: http://blog.jobbole.c ...
- 解析库之——beautifulsoup
阅读目录 一 介绍 二 基本使用 三 遍历文档树 四 搜索文档树 五 修改文档树 六 总结 一 介绍 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通 ...