先来看看如果遇到一个对象,如何判断其是否是这三种类型:

 from types import GeneratorType
from collectiuons import Iterable, Iterator isinstance( xx, GeneratorType )
isinstance( xx, Iterable )
isinstance( xx, Iterator )

生成器对象:

  生成器是一个通过yield关键字构建的函数,其返回一个generator对象,同时其又是一个iterator对象,因为其实现了__iter__与next方法

In[4]: def gene(k):
... for i in xrange(0, k):
... yield i
...
In[5]: ge = gene(6)
In[6]: type(ge)
Out[6]: generator
In[8]: dir(ge)
Out[8]: [ ...,'__iter__', 'next', ... ]
In[9]: isinstance(ge, collections.Iterator)
Out[9]: True

  生成器的一个特点是只能用一次

In[11]: for i in ge:
... print i
...
0
1
2
3
4
5
In[12]: ge.next()
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/IPython/core/interactiveshell.py", line 2820, in run_code
exec code_obj in self.user_global_ns, self.user_ns
File "<ipython-input-12-b9172cd6050f>", line 1, in <module>
ge.next()
StopIteration

迭代器对象:

  实现了__iter__与__next__方法的对象。

  __iter__返回一个实例作为最终使用的iterator对象--for...in...语句初始化时使用,next方法是后面每次迭代iterator对象时调用的方法

class Counter(object):
def __init__(self, low, high):
self.current = low
self.high = high def __iter__(self):
# 'Returns itself as an iterator object'
return self def next(self):
# 'Returns the next value till current is lower than high'
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
>>> c = Counter(5,10)
>>> for i in c:
... print(i, end=' ')
...
5 6 7 8 9 10
>>> for i in c:
...  pritn i
...
# 无输出
>>> c.next()
Traceback (most recent call last):
File "<ipython-input-12-b9172cd6050f>"
c.next()
StopIteration

可迭代对象:

  可迭代对象就是用于for...in...循环的

  不同于上面两种,其需要可以多次for...in...使用

  通过generator写可迭代对象:

  将__iter__写成生成器函数。注意for...in...时初始化时调用__iter__函数使得counter为low, 而后执行的都是yield所影响区域的了【1】,除非下次再执行for...in...语句才会调用到counter初始化那句,这样也就实现了复用。但是有个问题是此时Counter的实例就既不是generator也不是iterator对象了。故其也没法调用next方法

class Counter(object):
def __init__(self, low, high):
self.low = low
self.high = high def __iter__(self):
counter = self.low
while self.high >= counter:
yield counter
counter += 1 obj = Counter(5, 10)
print isinstance(obj, Iterator)
print isinstance(obj, GeneratorType)
print type(obj)
for i in obj:
print i
obj.next()

False
False
<class '__main__.Counter'>
5
6
7
8
9
10

Traceback (most recent call last):
File "/home/pd/..."
obj.next()
AttributeError: 'Counter' object has no attribute 'next'

注释【1】:

In [1]: def gener(k):
...: print "====initial===="
...: for i in range(0, k):
...: print "before yield"
...: yield i
...: print "after yield"
...: print "*****end******"
...: In [2]: g = gener(3)
In [3]: for i in g:
...: print g
...:
====initial====
before yield
<generator object gener at 0x7fbc8d15e870>
after yield
before yield
<generator object gener at 0x7fbc8d15e870>
after yield
before yield
<generator object gener at 0x7fbc8d15e870>
after yield
*****end******

补充:

  关于generator的yield与send:

  总的来说:yield返回的是个generator对象,send是向generator输送值

 In [35]: def gen():
...: while True:
...: print("before x_yield")
...: x=yield
...: print("after x_yield:", x)
...: yield x*2
...: print("after yield")
...:
...: In [36]: g = gen() In [37]: g.send(10)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-37-98b613a2ec82> in <module>()
----> 1 g.send(10) TypeError: can't send non-None value to a just-started generator In [38]: g.__next__(10)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-38-bc5eb41f1cb6> in <module>()
----> 1 g.__next__(10) TypeError: expected 0 arguments, got 1 In [39]: g.__next__()
before x_yield
# 由上可知, “x=yield”中的yield也会成为__next__()调用的终点,也就是说如果上面要两个__next__()才能走完。
31 # 通过实验发现,其实x=yield的执行并不是同时的,比如send(10),此时相当于到达了x=yield中的yield,而此时再执行send(11)才会执行x=yield这个赋值操作
31 # 所以输出是22而不是第一次就能传入的20【见43,44的输出】 In [40]: g.send(10)
after x_yield: 10
Out[40]: 20 # 进行到yield x*2 In [41]: g.__next__()
after yield
before x_yield In [42]: g.send(10)
after x_yield: 10
Out[42]: 20 In [43]: g.send(10) #
after yield
before x_yield In [44]: g.send(11)
after x_yield: 11
Out[44]: 22

补充:关于send与__next__()

 In [71]: def gen():
...: print("enhen")
...: while True:
...: print("before yield")
...: yield "pd the handsome"
...: print("afer yield")
...: In [72]: g=gen() In [73]: g.send(10)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-73-98b613a2ec82> in <module>()
----> 1 g.send(10) TypeError: can't send non-None value to a just-started generator In [74]: g.__next__()
enhen
before yield
Out[74]: 'pd the handsome'
# 由上可见,send(xx)并不能用于初始化调用generator, 但是通过 send(None)其实可以,纯粹的相当于74的调用__next__()
# 可见,send方法实际也调用了__next__()从而执行到了下一次的yield
In [75]: g.send(10)
afer yield
before yield
Out[75]: 'pd the handsome' In [76]: g.send(20)
afer yield
before yield
Out[76]: 'pd the handsome'

补充:用send实现协程【来源:寥雪峰

 def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK' def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n) // 执行一次c
print('[PRODUCER] Consumer return: %s' % r)
c.close() c = consumer()
produce(c) 执行结果: [PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

挺叼,传入个generator做操作!

补充:关于yield from :http://simeonvisser.com/posts/python-3-using-yield-from-in-generators-part-1.html

参考:

  http://pymbook.readthedocs.io/en/latest/igd.html

一篇关于yield的好文:

  http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do?rq=1

python中的generator, iterator, iterabel的更多相关文章

  1. python中的generator(coroutine)浅析和应用

    背景知识: 在Python中一个function要运行起来,它在python VM中需要三个东西. PyCodeObject,这个保存了函数的代码 PyFunctionObject,这个代表一个虚拟机 ...

  2. python中生成器generator

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

  3. Python中生成器generator和迭代器Iterator的使用方法

    一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...

  4. (转)Python中的generator详解

    本文转自:http://www.cnblogs.com/xybaby/p/6322376.html 作者:xybaby 注:本文在原文基础上做了一点点修改,仅仅作为个人理解与记忆,建议直接查看原文. ...

  5. python中的Iterable, Iterator,生成器概念

    https://nychent.github.io/articles/2016-05/about-generator.cn 这个深刻 谈起Generator, 与之相关的的概念有 - {list, s ...

  6. python中的生成器(generator)总结

    1.实现generator的两种方式 python中的generator保存的是算法,真正需要计算出值的时候才会去往下计算出值.它是一种惰性计算(lazy evaluation). 要创建一个gene ...

  7. python中yield用法

    在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何 ...

  8. [转]关于Python中的yield

    在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何 ...

  9. 【转载】关于Python中的yield

    在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何 ...

随机推荐

  1. 不定参数函数原理以及实现一个属于自己的printf函数

    一.不定参数函数原理 二.实现一个属于自己的printf函数 参考博文:王爽汇编语言综合研究-函数如何接收不定数量的参数

  2. 在uboot上创建菜单

    一.原理 菜单其实就是一个uboot中的命令,和其他的命令没有什么差别.  uboot启动时,如果进入uboot命令模式,先运行这个命令,就会打印出一个菜单界面. 在uboot的命令模式,通过键入“m ...

  3. google 论文

    从google历年所有论文的汇总来看,TOP5的分别是人工智能和机器学习.算法理论.人机交互与视觉.自然语言处理.机器感知,大家从一个侧面看出goolge research的重点了吧. Google所 ...

  4. commit日志历史不一致的Git仓库合并

    有个项目,用SVN commit的在国内开源中国的码云托管,可以直接Git clone"导出"一个本地的git仓库,我在Github上新建立了一个远程的仓库,准备把在码云上clon ...

  5. qml学习:对象和属性

    qml学习:对象和属性 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考文档<<Qt及Qt Quick开发实战精解.pdf>> ...

  6. zabbix 添加jvm监控

    1. zabbix 服务端安装,监控jmx 需要--enable-java zabbix 客户端不需要 --enable-java 2.zabbix_server端安装jdk 安装jdk [root@ ...

  7. (转载)php数组删除元素各种方法总结

    (转载)http://www.111cn.net/phper/php/46865.htm 有很多朋友都不知道怎么把数组中元素给删除,下面我来总结各种数组删除元素方法给各位,有需要了解的朋友可进入参考. ...

  8. UVAlive2531 The K-League(最大流)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33451 [思路] 最大流. 大体思路是枚举每个队伍,最大流判断是否 ...

  9. #345 div2 D. Image Preview

    Vasya's telephone contains n photos. Photo number 1 is currently opened on the phone. It is allowed ...

  10. SRM 394(1-250pt)

    DIV1 250pt 题意:给定一个字符串s('a'-'z'),计其中出现次数最多和最少的字母分别出现c1次和c2次,若在s中去掉最多k个字母,求去掉以后c1 - c2的最小值. 解法:做题的时候,想 ...