Python——迭代器和生成器
2016-10-19 21:53
441 查看
一、迭代器主要用于遍历操作,在iter方法中会返回一个迭代器,该迭代器包含next方法,在调用next方法时,迭代器返回它的下一个值。如果next方法被调用,但是迭代器没有值可以返回时,出发StopIteration异常。下面是一个求斐波那契数列的例子:
通过迭代可以自定义一个序列,如下:
二、生成器:通过普通的函数语法定义的迭代器,其创建如下:
包含yield语句的函数成为生成器,通常使用print语句进行输出,而使用yield语句可以是产生的值冻结,即函数会在冻结点等待激活,函数激活后会在停止的点开始执行。
创建的一般生成器只能处理两层循环,但是若要处理三层或者更多层数的循环需要使用递归生成器。
Flatten函数调用时会存在两种可能的情况,一种是需要递归展开,另一种是不需要递归展开。在不要递归展开的情况中,函数被告知展开一个元素,这种情况下,for循环会引发TypeError,生成器也会产生一个元素。对于需要展开的列表或者其他可以迭代的对象,函数会遍历所有子列表中的所有元素,并对他们再次调用flatten函数,然后在调用函数中通过循环来产生被展开自列表的所有元素。但是,递归生成器不能对字符串对象(包括字符串、Unicode、UserString等)进行迭代,这样导致出错。
对字符串进行迭代会出现错误,原因主要是flatten函数迭代时,需要把最终递归结束的迭代器作为原子对象,对于字符串来说并不是这样,在对字符串迭代时,Python并没有将字符串当成原子值,而是作为一个可以展开的序列就像迭代展开,因为就字符串而言,其中没有个字符又是一个可以展开的元素值。其次,对字符串的迭代会形成无穷递归,因为一个字符串的第一个元素是另一个长度为1的字符串,长度为1的字符串也就是字符串本身,又陷入了另一个长度为1的字符串的迭代。
若要对字符串作为基本元素进行迭代,需要在生成器开始的地方添加一个检查语句,将传入的对象和一个字符串拼接,看看是否出现TypeError。
或者通过instance检查类型:
参考文章:Magnus Lie Hetland的Python基础教程
# _*_ coding:utf-8 _*_ class Fibs: def __init__(self): self.a=0 self.b=1 def __next__(self): self.a,self.b=self.b,self.a+self.b return self.a def __iter__(self): return self fibs=Fibs() for f in fibs: if f > 1000: print(f) break 运行结果: ==========RESTART: C:\Users\Mr_Deng\Desktop\test.py========== 1597 >>>
通过迭代可以自定义一个序列,如下:
# _*_ coding:utf-8 _*_ class testList: value=0 def __init__(self,n=10): self.n=n def __next__(self): self.value+=1 if self.value > self.n: raise StopIteration return self.value def __iter__(self): return self 运行结果: ==========RESTART: C:\Users\Mr_Deng\Desktop\test.py========== >>> l=testList(20) >>> list(l) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] >>>
二、生成器:通过普通的函数语法定义的迭代器,其创建如下:
# _*_ coding:utf-8 _*_ nested=[[1,2],[3,4],[5]] def flatten(nested): for sublist in nested: for element in sublist: yield element 运行结果: ==========RESTART: C:\Users\Mr_Deng\Desktop\test.py========== >>> for num in flatten(nested): print(num) 1 2 3 4 5 >>> list(flatten(nested)) [1, 2, 3, 4, 5] >>>
包含yield语句的函数成为生成器,通常使用print语句进行输出,而使用yield语句可以是产生的值冻结,即函数会在冻结点等待激活,函数激活后会在停止的点开始执行。
创建的一般生成器只能处理两层循环,但是若要处理三层或者更多层数的循环需要使用递归生成器。
# _*_ coding:utf-8 _*_ __metaclass__=type def flatten(nested): try: for sublist in nested: for element in flatten(sublist): yield(element) except TypeError: yield nested 运行结果: ==========RESTART: C:\Users\Mr_Deng\Desktop\test.py========== >>> x=([1,2,3,[4,5],[1,2,[6,7]]]) >>> x [1, 2, 3, [4, 5], [1, 2, [6, 7]]] >>> list(flatten([1,2,3,[4,5],[1,2,[6,7]]])) [1, 2, 3, 4, 5, 1, 2, 6, 7] >>>
Flatten函数调用时会存在两种可能的情况,一种是需要递归展开,另一种是不需要递归展开。在不要递归展开的情况中,函数被告知展开一个元素,这种情况下,for循环会引发TypeError,生成器也会产生一个元素。对于需要展开的列表或者其他可以迭代的对象,函数会遍历所有子列表中的所有元素,并对他们再次调用flatten函数,然后在调用函数中通过循环来产生被展开自列表的所有元素。但是,递归生成器不能对字符串对象(包括字符串、Unicode、UserString等)进行迭代,这样导致出错。
>>> list(flatten('12345')) Traceback (most recent call last): File "<pyshell#18>", line 1, in <module> list(flatten('12345')) File "C:\Users\Mr_Deng\Desktop\test.py", line 6, in flatten for element in flatten(sublist): File "C:\Users\Mr_Deng\Desktop\test.py", line 6, in flatten for element in flatten(sublist): File "C:\Users\Mr_Deng\Desktop\test.py", line 6, in flatten
对字符串进行迭代会出现错误,原因主要是flatten函数迭代时,需要把最终递归结束的迭代器作为原子对象,对于字符串来说并不是这样,在对字符串迭代时,Python并没有将字符串当成原子值,而是作为一个可以展开的序列就像迭代展开,因为就字符串而言,其中没有个字符又是一个可以展开的元素值。其次,对字符串的迭代会形成无穷递归,因为一个字符串的第一个元素是另一个长度为1的字符串,长度为1的字符串也就是字符串本身,又陷入了另一个长度为1的字符串的迭代。
若要对字符串作为基本元素进行迭代,需要在生成器开始的地方添加一个检查语句,将传入的对象和一个字符串拼接,看看是否出现TypeError。
# _*_ coding:utf-8 _*_ __metaclass__=type def flatten(nested): try: try: nested+'' except TypeError: pass else: raise TypeError for sublist in nested: for element in flatten(sublist): yield(element) except TypeError: yield nested 运行结果: ==========RESTART: C:\Users\Mr_Deng\Desktop\test.py========== >>> list(flatten(['test',['asd',['qwe']],['pou']])) ['test', 'asd', 'qwe', 'pou'] >>>
或者通过instance检查类型:
# _*_ coding:utf-8 _*_ __metaclass__=type def flatten(nested): try: if isinstance(nested,str): raise TypeError for sublist in nested: for element in flatten(sublist): yield(element) except TypeError: yield nested ================= RESTART: C:\Users\Mr_Deng\Desktop\test.py ================= >>> list(flatten(['test',['asd',['qwe']],['pou']])) ['test', 'asd', 'qwe', 'pou'] >>> list(flatten('123')) ['123'] >>> list(flatten([1,2,3,[4,[6,7]]])) [1, 2, 3, 4, 6, 7] >>>
参考文章:Magnus Lie Hetland的Python基础教程
相关文章推荐
- python中迭代器、列表解析、生成器的分析比较
- Python 生成器函数,生成器表达式,迭代器,列表解析
- Python 生成器与迭代器
- 可爱的 Python: 迭代器和简单生成器
- Python斐波拉契生成器与迭代器
- python中的迭代器与生成器 .
- Python生成器和迭代器的关系
- python 从yield 学习迭代器和生成器
- python中的迭代器与生成器详解
- Python中的新型构造迭代器和简单生成器
- 强大的Python 迭代器和简单生成器
- Python迭代器与生成器(转)
- python中的迭代器与生成器
- Python的迭代器和生成器
- ·python·用生成器和迭代器实现自己的xrange
- ·python·用生成器和迭代器实现自己的xrange
- python·用生成器和迭代器实现自己的xrange
- python学习笔记之八:迭代器和生成器
- python中的迭代器与生成器
- python迭代器和生成器