Python核心编程之迭代器和生成器


迭代器和iter()函数
(1)什么是迭代器

    迭代器是版本2.2被加入Python中的,它为类序列对象提供了一个类序列的接口。
(2)为什么要迭代器
    引用PEP(234)中对迭代器的定义:
<1>提供了可扩展的的迭代器借口;
<2>对列表迭代带来了性能上的增强;
<3>在字典迭代中性能提升;
<4>创建真正的迭代借口,而不是原来的随机对象访问;
<5>与所有已经存在的用户定义的类以及扩展的模拟序列和映射的对象的后向兼容;
<6>迭代非序列集合(例如映射文件)时,可以创建更简洁可读的代码。
(3)如何迭代
    根本上说,迭代器就是一个有next()方法的对象,而不是通过索引来计数。条目全部取出以后,会引发一个StopIteration异常,这并不表示错误发生,只是告诉外部调用者,迭代完成。
    迭代器有一些限制。例如不能向后移动,不能回到开始,也不能复制一个迭代器。
    reversed()内建函数返回一个反向访问的迭代器。enumerate()内建函数同样也返回迭代器。any()和all(),如果迭代器中某个/所有条目的值都为布尔真时,它们的返回值为真。Python提供了一整个itertools模块,它包含各种有用的迭代器。
(4)使用迭代器
序列

>>> myTuple = (123,'xyz',45.67)
>>> i = iter(myTuple)
>>> i.next()
123
>>> i.next()
'xyz'
>>> i.next()
45.670000000000002
>>> i.next()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
StopIteration
如果这是一个实际的应用程序,我们需要把代码放在一个try-catch块中。序列现在会自动地产生它们自己的迭代器,所以一个for循环:
for i in seq:
    do_somthing_to(i)
实际上是这样工作的:
fetch = iter(seq)
while True:
     try:
         i = fetch.next()
     except StopItertation:
         break
     do_somthing_to(i)
for循环会自动调用迭代器的next方法,所以代码Just so.
字典
字典和文件是另外两个可以迭代的Python数据类型。字典的迭代器会遍历它的键。
文件
文件对象生成的迭代器会自动调用readline()方法。


(5)迭代器的创建
iter(obj)   一个实现了__iter__()和next()方法的类可以作为迭代器使用。
iter(func,sentinel)  它会反复地调用func,直到迭代器的下个值等于sentinel.


(6)列表解析(list comprehensions,or list comps for short)
    列表解析来自函数式编程语言Haskell。它是一个非常有用、简单而且灵活的工具,可以用来动态地创建列表。应用lambda、map()和filter()等方法啊可以灵活地创建列表。
列表解析的语法
[expr for iter_var in iterable]
[expr for iter_var in iterable if cond_expr]
>>> map(lambda x:x**2 ,range(6))
[0, 1, 4, 9, 16, 25]
>>> [x ** 2 for x in range(6)]
[0, 1, 4, 9, 16, 25]
>>> seq = [11,10,9,9,10,10,9,8,23,9,7,18,12,11,12]
>>> def ord(n):
...     return n % 2
>>> filter(lambda x:x%2, seq)
[11, 9, 9, 9, 23, 9, 7, 11]
>>> [x for x in seq if x % 2]
[11, 9, 9, 9, 23, 9, 7, 11]
>>>[(x+1,y+1) for x in range(3) for y in range(5)]
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5)]


(7)生成器表达式
    生成器是特定的函数,允许你返回一个值,然后“暂停”代码的执行,稍后恢复。列表解析的一个不足就是必要生成所有的数据,所以用以创建整个列表。这可能对有大量数据的迭代器有负面效应。生成器表达式通过结合列表解析和生成器解决了这个问题。
    生成器表达式使用了“延迟计算”(lazy evaluation),所以它在使用内存上更有效。生成器表达式和列表解析及其相似:
(expr for iter_var in iterable if cond_expr)
列表解析:
[expr for iter_var in iterable if cond_expr]
>>> generator = (i for i in range(5))
>>> for obj in generator:
...     print obj,
...     
0 1 2 3 4


    Python支持通过yield语句实现的生成器,简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。这个机制可以很方便地实现一些东西,比如《Expert Python Programming》给出的这个生成fibonacci数列的例子:
def fibonacci():
  a, b = 0, 1
  while True:
    yield b
    a, b = b, a + b
fib = fibonacci()
for i in range(10):
  print fib.next(),

    这个例子可以求出fibonacci数列的前10项,而且当需要下一项的时候只需要fib.next()就可以了。    

    除了从获取生成器的结果,还可以给生成器发送值,另外还以可以关闭生成器生成进程。由于双向的动作涉及叫做send()的代码来向生成器发送值(以及生成器返回的值发送回来),现在yield语句必须是一个表达式(feel it),因为当回到生成器中继续执行的时候,你或许正在接受一个进入的对象。例:

def counter(start_at = 0):
    count = start_at
    while True:
        val = (yield count)
        if val is not None:
            count = val
        else:
            count += 1

count = counter(5)
print count.next()
print count.next()
print count.send(9)
print count.next()
print count.close()
print count.next()

5
6
9
10
None
Traceback (most recent call last):
  File "xxxxxxxxxxxxxxxxxxxxxxxxxx", line xxxx, in <module>
    print count.next()
StopIteration



REF:http://blog.csdn.net/CherylNatsu/article/details/6403327

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值