python 迭代器与生成器
2017-11-08 19:09
323 查看
参考:
1.http://python.jobbole.com/81916/
2.http://blog.csdn.net/bluebird_237/article/details/38894617
3.http://www.runoob.com/python3/python3-iterator-generator.html
可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
所有的Iterable均可以通过内置函数iter()来转变为Iterator。
对于迭代器而言,通过next()函数实现“迭代”这一概念,在使用for in语句的时候,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的next方法,当长度超过了迭代器长度时,就会报StopIteration的异常。
有以下结论:
1.内置函数iter()仅仅是调用了对象的iter()方法,所以list对象内部一定存在方法iter()
2.内置函数next()仅仅是调用了对象的next()方法,所以list对象内部一定不存在方法next__(),但是Itrator中一定存在这个方法
3.for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的
可以通过下面这个例子进一步说明:
4.Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含iter()和next()方法,而Iteratble仅仅包含iter()。
还有一个需要注意的地方,那就是迭代器是一次性消耗品,使用完了就无法倒退,因此如果需要多次使用需要进行复制。
如何解决呢?
python2.x似乎只能通过重新生成来实现
通过
从说明中我们可以看出,直接使用iter函数返回迭代器,需要对象能调用自身的iter函数得到iterator或者是一个序列(序列化)。
序列化相关的内容,博主还不太了解以后学习深入了可以回来补一下。
在不做序列化处理的条件下,实现自定义类的可iter(),需要自己实现iter()函数。
上面的代码中也可以将两个类合在一起写,这到无关紧要。
到目前为止,我们得到迭代器都是通过iter()函数转化原对象为iterator,并调用next方法实现迭代操作。
如果我们只是单纯的想做一些迭代的操作(可以节省内存),如不断去计算类里面一些值并结果,而不想把它当做类的next()方法又该如何呢?
这个时候就需要生成器了。
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
举个例子,我们希望有一个基于菲波那切数列的循环操作
1.通过控制条件,实现变量的斐波那契额变化
这样说可以实现的,但是复用性太差,每次如果操作改了都得重新再做一次菲波那切变化,并写函数体
2.获得这样一个菲波那切数列并通过for in迭代,但是如果该数列较大,占用内存也较大
3.得到一个可迭代对象,next()函数符合菲波那切变化
这样的一种方式比较好,如果通过之前的说法我们最起码得自定义一个类实现next()方法,但这样的工作实在没必要,为此python通过yield实现了将所需函数转化为对应next()函数,并返回iterator对象的操作,这样一来相当于你只需要写next()函数的内容便可以轻松得到自定义的迭代器。
1.http://python.jobbole.com/81916/
2.http://blog.csdn.net/bluebird_237/article/details/38894617
3.http://www.runoob.com/python3/python3-iterator-generator.html
迭代器
先了解几个概念:可以直接作用于for循环的对象统称为可迭代对象(Iterable)。
可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
所有的Iterable均可以通过内置函数iter()来转变为Iterator。
对于迭代器而言,通过next()函数实现“迭代”这一概念,在使用for in语句的时候,程序就会自动调用即将被处理的对象的迭代器对象,然后使用它的next方法,当长度超过了迭代器长度时,就会报StopIteration的异常。
>>> a=[1,2,3] >>> for i in a: ... print(i) ... 1 2 3 >>> next(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list object is not an iterator >>> I=iter(a) >>> for i in I: ... print i ... 1 2 3 >>> next(I) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
有以下结论:
1.内置函数iter()仅仅是调用了对象的iter()方法,所以list对象内部一定存在方法iter()
2.内置函数next()仅仅是调用了对象的next()方法,所以list对象内部一定不存在方法next__(),但是Itrator中一定存在这个方法
3.for循环内部事实上就是先调用iter()把Iterable变成Iterator在进行循环迭代的
可以通过下面这个例子进一步说明:
>>> a=[1,2,3] >>> I=a.__iter__() >>> a.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'list' object has no attribute 'next' >>> I.next() 1 >>> from collections import Iterator, Iterable >>> isinstance(a,Iterator) False >>> isinstance(a,Iterable) True >>> isinstance(I,Iterable) True >>> isinstance(I,Iterator) True
4.Iterator继承自Iterable,从下面的测试中可以很方便的看到Iterator包含iter()和next()方法,而Iteratble仅仅包含iter()。
>>> from collections import Iterator, Iterable >>> help(Iterator) Help on class Iterator: class Iterator(Iterable) | Method resolution order: | Iterator | Iterable | builtins.object |**注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 | Methods defined here: | | __iter__(self) | | __next__(self) | Return the next item from the iterator. When exhausted, raise StopIteration ...... >>> help(Iterable) Help on class Iterable: class Iterable(builtins.object) | Methods defined here: | | __iter__(self) ......
还有一个需要注意的地方,那就是迭代器是一次性消耗品,使用完了就无法倒退,因此如果需要多次使用需要进行复制。
>>> I=iter([1,2,3]) >>> for i in I: ... pass ... #此时迭代器I已消耗完 >>> next(L) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'L' is not defined #然而一开始的复制并没有起作用
如何解决呢?
python2.x似乎只能通过重新生成来实现
生成器
在讲生成器之前,我们先讲讲如何使得自己自定义的类变为Iterable通过
help(iter)查看一下:
iter(...) iter(collection) -> iterator iter(callable, sentinel) -> iterator Get an iterator from an object. In the first form, the argument must supply its own iterator, or be a sequence. In the second form, the callable is called until it returns the sentinel.
从说明中我们可以看出,直接使用iter函数返回迭代器,需要对象能调用自身的iter函数得到iterator或者是一个序列(序列化)。
序列化相关的内容,博主还不太了解以后学习深入了可以回来补一下。
在不做序列化处理的条件下,实现自定义类的可iter(),需要自己实现iter()函数。
class Iterable: def __iter__(self): return Iterator() class Iterator: def __init__(self): self.start=-1 def next(self): self.start +=2 return self.start I = Iterable() for count, i in zip(range(5),I): print(i) 输出:1,3,5,7,9
上面的代码中也可以将两个类合在一起写,这到无关紧要。
到目前为止,我们得到迭代器都是通过iter()函数转化原对象为iterator,并调用next方法实现迭代操作。
如果我们只是单纯的想做一些迭代的操作(可以节省内存),如不断去计算类里面一些值并结果,而不想把它当做类的next()方法又该如何呢?
这个时候就需要生成器了。
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
举个例子,我们希望有一个基于菲波那切数列的循环操作
1.通过控制条件,实现变量的斐波那契额变化
这样说可以实现的,但是复用性太差,每次如果操作改了都得重新再做一次菲波那切变化,并写函数体
2.获得这样一个菲波那切数列并通过for in迭代,但是如果该数列较大,占用内存也较大
3.得到一个可迭代对象,next()函数符合菲波那切变化
这样的一种方式比较好,如果通过之前的说法我们最起码得自定义一个类实现next()方法,但这样的工作实在没必要,为此python通过yield实现了将所需函数转化为对应next()函数,并返回iterator对象的操作,这样一来相当于你只需要写next()函数的内容便可以轻松得到自定义的迭代器。
def fibonacci(n): # 生成器函数 - 斐波那契 a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1 f = fibonacci(10) # f 是一个迭代器,由生成器返回生成 while True: try: print next(f) except StopIteration: print("done") break 输出:0,1,1,2,3,5,8,13,21,34,55
相关文章推荐
- Python基础-迭代器与yield生成器
- Python 迭代器和生成器
- python中迭代器和生成器的区别
- python的迭代器与生成器实例详解
- Python 迭代器 生成器
- python 迭代器、生成器基础知识
- python学习笔记四 迭代器,生成器,装饰器(基础篇)
- Python迭代器与生成器实例演示
- python基础----迭代器、生成器、协程函数及应用(面向过程实例)
- python中的迭代器与生成器
- Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化
- Python 可迭代的对象、迭代器和生成器
- Python基础之生成器、迭代器
- 【Python】迭代器、生成器、yield单线程异步并发实现详解
- python 迭代器 生成器
- Python学习笔记——迭代器和生成器
- python 生成器和迭代器有这篇就够了
- python3 迭代器与生成器整理12.24
- 可爱的 Python: 迭代器和简单生成器
- python中的迭代器和生成器