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

 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. ASP.NET MVC轻教程 Step By Step 3 ——使用ViewBag

    在上一节我们创建了与Index动作方法对应的Index视图,那么Index动作方法该如何向Index视图传送数据呢?其中一个方法是使用ViewBag(视图包).让我们试试看. 在Index动作方法中添 ...

  2. C#窗体程序画倾斜一定角度的椭圆

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  3. BZOJ 1492 货币兑换

    Description Input 第一行两个正整数\(N,S\),分别表示小Y 能预知的天数以及初始时拥有的钱数. 接下来\(N\)行,第\(K\)行三个实数\(A_{K},B_{K},Rate_{ ...

  4. cf D. Physical Education and Buns

    http://codeforces.com/contest/394/problem/D 题意:给你n个数,然后通过操作使得这n个数变为一个等差数列,操作是可以经过小于等于k次加1或减去1,要使得k尽量 ...

  5. iOS手写2048--基于Xcode7.1

    闲着没事自己想了下,半天写出来了,没有美化,只是实现了基本的2048,被我改成了A.B.C.D.E: 没有游戏开发经验,完全基于uiview 和 一大堆逻辑计算,如果你有指针.链表的使用经验,应该会很 ...

  6. OTP语音芯片和掩模语音芯片(mask)的区别

    OTP(One Time Programable)是MCU的一种存储器类型,意思是一次性可编程:程序烧入IC后,将不可再次更改和:因此OTP语音芯片就是指一次性烧录的语音IC. 从OTP定义上来看,只 ...

  7. The Same Game(模拟)

    http://poj.org/problem?id=1027 题意:给一个10*15的地图,里面填充R,G,B三种颜色,每次找到当前地图的同色最大区域M,并将其删除,删除M后,上面的小球自然下落,当有 ...

  8. Lucky and Good Months by Gregorian Calendar(模拟)

    http://poj.org/problem?id=3393 好大的一道模拟题,直接当阅读理解看了.下面是大神写的题意,解释的好详细. 定义: Goog month : 该月第一个工作日为星期一的月份 ...

  9. HDU 1151 Air Raid(最小路径覆盖)

    题目大意: 有n个城市,m条道路,城市的道路是单向.  现在我们的伞兵要降落在城市里,然后我门的伞兵要搜索所有道路.问我们最少占领多少个城市就可以搜索所有的道路了. 我们可以沿着道路向前走到达另一个城 ...

  10. 数学(莫比乌斯反演):HAOI 2011 问题B

    题目描述: 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 输入格式: 第一行一个整数n,接下来n ...