[python]Generators
generators(生成器)是python提供的一种机制,可以让函数一边循环一边计算,通常函数是一遍执行,而生成器可以在执行中间交出变量,下次调用时从交出变量的地方重新开始,这种机制通过yield关键字实现。
考虑生成斐波那契数,即1,1,2,3,5,8......、
假设我不指定生成的项数,而通过调用next()的方法不断循环下一个数,那么代码应该如下:
class Fib(object):
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def next(self):
self.a, self.b = self.b, self.a + self.b
if self.a > 100000:
raise StopIteration()
return self.a
实际上这么编写的Fib类已经实现了迭代器(Iterator)的功能,因为实现了__iter__()和next()方法,在一个实例中调用next()方法可以不断的得到下一个斐波拉契数,而用for循环时则会先调用__iter__()方法,该方法返回一个实例,再去调用该实例的next()方法。
其实这里好像已经实现不断迭代的功能了(笑),然而我们一开始是要用生成器来实现的,那生成器应该怎么做。
def fib():
a,b=0,1
while(a<100000):
a,b=b,a+b
yield a
如此就编写了一个生成器,代码真是精简(捂脸)......
同样的,a=fib()后,a可以调用next()方法,并且a也可以用for循环,结果与迭代器一致。
注意这里如果直接调用fib().next()则每次输出都是1,1,1,1,1,1
打印一下fib().next看看
fib().next
<method-wrapper 'next' of generator object at 0x0000000003AEFEE8>
fib().next
<method-wrapper 'next' of generator object at 0x0000000003B553F0>
可以看到两次的地址不一致,其实就是创建了一个方法而已,再看看fib跟fib()的区别:
fib
<function fib at 0x0000000003B4FAC8>
fib()
<generator object fib at 0x0000000003AEFD38>
一个是函数,一个是生成器。
因此a=fib是指向了fib方法,a=fib()才是”继承“了一个生成器。
在廖雪松的Python教程中生成器一节有一个杨辉三角练习
def triangles():
L=[1]
while(True):
yield L
L.append(0)
L = [L[i-1]+L[i] for i in range(len(L))]
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]
这段代码没有难度,不过里面用到的一个小技巧就是L[-1]+L[0]中L[-1]其实是L的最后一个元素,也就是新添加的0,这样十分巧妙地将需要往L中首尾添加0的情形变为只要末尾添加0就行了,十分的耐人寻味。
yield的用法其实不止体现在生成器中,在Python的上下文管理中也有体现。例如某个过程的上下文管理如下:
from contextlib import contextmanager
@contextmanager
def context():
print "Begin"
yield
print "End" with context():
print "a process"
因为context()实现了上下文管理,所以可以用with来调用,当执行倒yield时,函数退出交给实际的process处理,完成后再继续调用yield后面的语句结束。输出结果为:
Begin
a process
End
总结:
Python中生成器的编写主要是用到了yield关键字,让函数能够”停下来“一次一次地输出,迭代器能实现同样的功能,但迭代器要实现__iter__()和next()方法。
http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000
http://blog.csdn.net/scelong/article/details/6969276
[python]Generators的更多相关文章
- (转) Python Generators(生成器)——yield关键字
http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...
- Python Generators(生成器)--yield
参考:http://blog.csdn.net/scelong/article/details/6969276 Python生成器 什么是python生成器,意思是带有一个yield语句的函数,既然它 ...
- Python Generators vs Iterators
http://stackoverflow.com/questions/2776829/difference-between-python-generators-vs-iterators iterato ...
- Python资源大全
The Python Tutorial (Python 2.7.11) 的中文翻译版本.Python Tutorial 为初学 Python 必备官方教程,本教程适用于 Python 2.7.X 系列 ...
- Python’s SQLAlchemy vs Other ORMs[转发 5] PonyORM
PonyORM PonyORM allows you to query the database using Python generators. These generators are trans ...
- 十二. Python基础(12)--生成器
十二. Python基础(12)--生成器 1 ● 可迭代对象(iterable) An object capable of returning its members one at a time. ...
- python coroutine的学习跟总结[转]
简介 因为最近一段时间需要研究一些openstack相关的东西,在阅读一些相关代码的时候碰到很多python特定的一些特性,比如generator, coroutine以及一些相关的类库,比如even ...
- Python 协程与事件循环
Table of Contents 前言 协程 async & await 事件循环 asyncio 的事件循环 结语 参考链接 前言 Python 标准库 asyncio 是我目前接触过的最 ...
- [Python] Use a Python Generator to Crawl the Star Wars API
In this lesson, you will be introduced to Python generators. You will see how a generator can replac ...
随机推荐
- MySQL5.7 GTID学习笔记
GTID(global transaction identifier)是对于一个已提交事务的全局唯一编号,前一部分是server_uuid,后面一部分是执行事务的唯一标志,通常是自增的. 下表整理了G ...
- python自学第11天-单线程并发、迭代器,序列化,获取路径
单线程并发 import time def consumer(name): print("%s 准备吃包子了"%name) while True: baozi=yield#变成一个 ...
- 当你在web项目下新建一个class时package位置如果发生红色波浪错误,提示为”The type java.io.ObjectInputStream cannot be resolved. It is indirectly referenced from required .class files“
问题是这样的如下图: 问题的原因: 1.配置tomcat7.0的时候自己设置了jre的版本1.8,而没有用myeclipse10自带的jre1.6,导致了出现了差错!
- js使页面重定向
location.assign("http://www.baidu.com"); window.location="http://www.baidu.com"; ...
- 2--Postman脚本介绍
Postman是访问各种API的客户端.它的强大之处在于其允许在对某一个request访问的之前和之后分别运行自定义的一段Javascript脚本,可以将数条request连结成一个流程完成一体化测试 ...
- 自动化测试-1.selenium简介
1. selenium一个自动化测试工具,适用于测试web系统2. selenium支持多种编程语言:python .java .c#.ruby3.selenium支持多浏览器,selenium脚本可 ...
- css新增伪类
:first-of-type p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素. :last-of-type p:last-of-typ ...
- 排序算法练习--JAVA(:内部排序:插入、选择、冒泡、快速排序)
排序算法是数据结构中的经典算法知识点,也是笔试面试中经常考察的问题,平常学的不扎实笔试时候容易出洋相,回来恶补,尤其是碰到递归很可能被问到怎么用非递归实现... 内部排序: 插入排序:直接插入排序 选 ...
- oracle获取连续时间
SELECT rownum, (to_date('2015-01-01', 'yyyy-mm-dd') + rownum - 1) AS show_time FROM dualCONNECT BY r ...
- Oracle的导入和导出
导出命令: EXP 用户名/密码@数据库名 BUFFER=64000 file=G:\dmp\full1.dmp OWNER=用户名 导入命令: IMP 用户名/密码@数据库名 BUFFER=64 ...