Python8-26

迭代器(iterator)

  有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器物件的内容。
  在python中,对迭代器的定义是为类似序列的对象提供了一个具有序列特性的接口。它是在python2.2版本中引进进来的。python的迭代器无缝地支持序列对象,而且它还支持非序列类型,包括用户定义的对象。

迭代器的作用(优点)

  • PEP234中对迭代器的作用有着明确的记录:
  • 提供了可扩展的迭代器接口;
  • 对字典、列表的迭代带来了性能的提升;它一次只返回一个数据项,占用更少的内存。但它需要记住当前的状态,以便返回下一数据项。
  • 创建真正的迭代接口,而不是原来的随机对象访问;
  • 与所有已经存在的用户定义的类以及扩展的模块序列和映射的对象向后兼容;
  • 迭代非序列对象时,可以创建更加简洁可读的代码;

迭代器的缺点

迭代器不能回退,只能往前进行迭代。迭代器也不是线程安全的,在多线程环境中对可变集合使用迭代器是一个危险的操作。但如果小心谨慎,或者干脆贯彻函数式思想坚持使用不可变的集合,那这也不是什么大问题

 

>>>i = iter(abc)
>>>i.next()
a
>>>i.next()
b
>>> class MyIterator(object):
...     def __init__(self,step):
...             self.step=step
...     def next(self):
...             if self.step ==0:
...                     raise StopIteration
...             self.step-=1
...             return self.step
...     def __iter__(self):
...             return self
... 
>>> for mi in MyIterator(4):
...     print mi
... 
3
2
1
0

生成器

  生成器提供了一种出色的方法,使得需要返回一系列元素的函数所需的代码更加简单、高效。

  基于yield指令,可以暂停一个函数别返回中间结果。

In [1]: def fibonacci():
   ...:     a,b=0,1
   ...:     while True:
   ...:         yield b
   ...:         a,b=b,a+b
   ...:         

In [2]: fib=fibonacci()

In [3]: fib.next()
Out[3]: 1

In [4]: fib.next()
Out[4]: 1

In [5]: fib.next()
Out[5]: 2

In [6]: [fib.next() for i in range(10)]
Out[6]: [3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

  链接多个函数

In [10]: def power(values):
   ....:     for value in values:
   ....:         print powering %s%value
   ....:         yield value
   ....: 

In [12]: def adder(values):
   ....:     for value in values:
   ....:         print adding to %s % value
   ....:         if value % 2==0:
   ....:             yield value+3
   ....:         else:
   ....:             yield value+2
   ....:             

In [13]: elements=[1,4,7,9,12,19]

In [14]: res=adder(power(elements))

In [15]: res.next()
powering 1
adding to 1
Out[15]: 3

In [16]: res.next()
powering 4
adding to 4
Out[16]: 7

  yield还可以变为一个表达式,通过send方法传递。

 def psychologist():
   ....:     print Please tell me your problems
   ....:     while True:
   ....:         answer=(yield)
   ....:         if answer is not None:
   ....:             if answer.endswith(?):
   ....:                 print ("Don‘t ask yourself too much questions")
   ....:             elif good in answer:
   ....:                 print "A that‘s good,go on"
   ....:             elif bad in answer:
   ....:                 print "Don‘t be so negative"
   ....:                 

In [20]: free=psychologist()

In [21]: free.next()
Please tell me your problems

In [24]: free.send(I feel bad)
Dont be so negative

In [25]: free.send(I feel bad?)
Dont ask yourself too much questions

  send的工作机制和next一样,但是yied将变成能够返回传入的值。因而,这个函数可以根据客户端行为改变自身行为。

  一个典型的生成器模板应该类似于:

In [31]: def my_generator():
   ....:     try:
   ....:         yield something
   ....:     except ValueError:
   ....:         yield dealing with the exception
   ....:     finally:
   ....:         print "ok let‘s clean"
   ....:         

In [32]: gen=my_generator()

In [33]: gen.next()
Out[33]: something

In [34]: gen.throw(ValueError(mean mean))
Out[34]: dealing with the exception

In [35]: gen.close()
ok lets clean

In [37]: gen.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
/home/zxp/<ipython-input-37-b2c61ce5e131> in <module>()
----> 1 gen.next()

StopIteration: 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。