Python 生成器 Generator 和迭代器 Iterator
#最近一周刚开始接触python,基本的语法,和使用特性和Java差别还是蛮大的。
今天接触到Python的迭代器和生成器有点不是很明白,所以搜索了先关资料整理了一些自己的理解和心得
简述(Profile):
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
Iteration one of Python's most powerful functions and a way to access colleaction elements.
迭代器是一个可以记住遍历位置的对象。
An iterator is an object that can remenber to traverse the location.
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
The Iterator onject starts from the first element of the collection until all the elements are accessed. The iterator can only move forward without going backwards.
迭代器有两个基本的方法:iter() 和 next().
Iterator have two basic methods: iter() and next()
字符串,列表和元组对象都可用于创建迭代器:
Strings, lists, and tuples can be used to create iterators:
>>>list=[1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print (next(it)) # 输出迭代器的下一个元素
1
>>> print (next(it))
2
>>>
实例(Instance)
迭代器可以使用常规for语句进行遍历:
Iterators can be traversed using the resular for statements:
#!/usr/bin/python3 list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
执行以上程序,输出结果如下:
The above procedures are performed and the output results are as follows:
1 2 3 4
生成器的背景:(Background Of Generator)
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
With a list generation, we can create a list directly. However, with memory constraints, the list capacity is centainly limited. And create a list containing 1 million elements, not only takes up a lof of storage space, if we only need access to the front several elemts, that behind the vast majaority of the elements to take up the space is wasted.
所以,如果列表可以通过某种算法算出来,那我们是否可以在循环的过程中不断地推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制称之为生成器(Generator)。
So, if the list can be calculated by some algorithm, So can we constanly extrapolate the following elements in the loop? This saves a lot of space by not creating a complete list. In Python, the mechanism of this side loop is called a Generator.
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
There are many ways to create a generator. The first method is simple, so if you change a list to (), you create a generator:
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>
创建L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
The difference between creating L and g is only the outermost [] and (), L is a list, and g is a generator.
如果要一个一个打印出来,可以通过generator的g.__next__()或者next(g)
方法:(在Python2 中使用的是g.next()方法)
If you want to print them one by one, you can use the g.__next() or next(g) mehod of generator:
>>> g.__next__()
0
>>> g.__next__()
1
>>> g.__next__()
4
>>> g.__next__()
9
>>> g.__next__()
16
>>> g.__next__()
25
>>> g.__next__()
36
>>> g.__next__()
49
>>> g.__next__()
64
>>> g.__next__()
81
>>> g.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
generator保存的是算法,每次调用__next__()
,就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
The generator saves the algorithm, and each time it calls __next__(), it computes the value of the next element until the last element is calculated, and when there is no more elements, the error of StopIteration is thrown.
generator 非常强大。如果推算的算法比较复杂,总类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
The generator is very powerful. If the calculated algorithm is more complex, the "for loop" of the list generation is not realized, and the function can be used to realize it.
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
For example, the famous Fibonacci sequence (Fibonacci), except for the first and second Numbers, any number can be added by the first two Numbers:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
The Fibonacci sequence can't be written out of the list, but it's easy to print it out with a function:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
上面的函数可以输出斐波那契数列的前N个数:
The above function can output the first N numbers of the Fibonacci sequence:
>>> fib(6)
1
1
2
3
5
8
仔细观察,可以看出,fib
函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
If you look closely, you can see that fib is actually defines the Fibonacci ratched series calculations rules, can start on the first element, determine the subsequent arbitrary elements, this logic is very simialr to the generator.
也就是说,上面的函数和generator仅一步之遥。要把fib
函数的返回值变成generator,只需要把print b
改为yield b
就可以了:
In other words, the above functions is just one step away from the generator. To turn the return value of the fib function into the generator, just change the 'print(b) to yield b.
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
这就是定义generator的另一种方法。如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,它的返回值就是是一个generator:
This is another way to define the generator. If a function definition contains the yield keyword, the function is no longer a normal function, and its return value is a generator.
举个简单的例子,定义一个generator,依次返回数字1,3,5:
For a simple example, define a generator and return the number 1,3,5:
>>> def odd():
... print 'step 1'
... yield 1
... print 'step 2'
... yield 3
... print 'step 3'
... yield 5
...
>>> o = odd()
>>> o.__next__()
step 1
1
>>> o.__next__()
step 2
3
>>> o.__next__()
step 3
5
>>> o.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
可以看到,odd
不是普通函数,它的返回值是generator,在执行过程中,遇到yield
就中断,下次又继续执行。执行3次yield
后,已经没有yield
可以执行了,所以,第4次调用next()
就报错。
As you can see, odd is nor a normal function, and its return value is the generator. In the execution process, the yield is interrunpted and the next time it is executed. After executing the yield three times, there no yield to be executed, so the forth call to next() is an error.
回到fib
的例子,我们在循环过程中不断调用yield
,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。
So back to the fib example, we're constanly calling the yield, and it's going to break. Of cause, you have to set a condition for the loop exit the loop, or you'll have a infinite number.
同样的,把函数改成generator后,我们基本上从来不会用next()
来调用它,而是直接使用for
循环来迭代:
Similarly, after changing the function to the generator, we basically never involke it with next(), but instead use the for loop to iterate:
>>> for n in fib(6):
... print n
...
1
1
2
3
5
8
Reference Documents: https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138681965108490cb4c13182e472f8d87830f13be6e88000
Python 生成器 Generator 和迭代器 Iterator的更多相关文章
- python生成器(generator)、迭代器(iterator)、可迭代对象(iterable)区别
三者联系 迭代器(iterator)是一个更抽象的概念,任何对象,如果它的类有next方法(next python3)和__iter__方法返回自己本身,即为迭代器 通常生成器是通过调用一个或多个yi ...
- 生成器generator和迭代器Iterator
一.列表生成式 在学习生成器迭代器之前先了解一下什么是列表生成式,列表生成式是Python内置的非常简单却强大的可以用来创建list的生成式.什么意思?举个例子,如果想生成列表[0,1,2 ...
- Python之生成器(generator)和迭代器(Iterator)
generator 生成器generator:一边循环一边计算的机制. 生成器是一个特殊的程序,可以被用于控制循环的迭代行为.python中的生成器是迭代器的一种,使用yield返回值函数,每次调用y ...
- Python中生成器generator和迭代器Iterator的使用方法
一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...
- 【python之路29】python生成器generator与迭代器
一.python生成器 python生成器原理: 只要函数中存在yield,则函数就变为生成器函数 #!usr/bin/env python # -*- coding:utf-8 -*- def xr ...
- 学习python第十二天,函数4 生成器generator和迭代器Iterator
在Python中,这种一边循环一边计算的机制,称为生成器:generator 要创建一个generator,有很多种方法.第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个genera ...
- Python 生成器 (generator) & 迭代器 (iterator)
python 生成器 & 迭代器 生成器 (generator) 列表生成式 列表生成式用来生成一个列表,虽然写的是表达式,但是储存的是计算出来的结果,因此生成的列表受到内存大小的限制 示例: ...
- 【Python之路】特别篇--生成器(constructor)、迭代器(iterator)、可迭代对象(iterable)
生成器(constructor) 生成器函数在Python中与迭代器协议的概念联系在一起.包含yield语句的函数会被特地编译成生成器 !!! 当函数被调用时,他们返回一个生成器对象,这个对象支持迭代 ...
- Python学习笔记014——迭代器 Iterator
1 迭代器的定义 凡是能被next()函数调用并不断返回一个值的对象均称之为迭代器(Iterator) 2 迭代器的说明 Python中的Iterator对象表示的是一个数据流,被函数next()函数 ...
随机推荐
- Android之通过HttpURLConnection.getResponseCode状态码抛出异常的问题以及解决方法
1.最近,在学习解析json数据的时候遇到一个错误信息,错误信息如下图所示: 发现解析出来的数据为空,错误信息如上图所示,发现程序中的HttpUtils工具类的22行出现了错误和MainActiv ...
- 51nod 1445 变色DNA ( Bellman-Ford算法求单源最短路径)
1445 变色DNA 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一只特别的狼,它在每个夜晚会进行变色,研究发现它可以变成N种颜色之一,将这些颜色标号为0,1 ...
- 紫书 例题 11-5 UVa 10048 (Floyd求最大权值最小的路径)
这道题是Floyd的变形 改成d[i][j] = min(d[i][j], max(d[i][k], d[k][j]))就好了. #include<cstdio> #include< ...
- Eclipse集成Git插件及使用
目录(?)[+] 1 Git插件安装 11 下载插件 2 Git提交代码 21 建git的本地仓库 第一种 第二种 项目创建本地仓库后 如图 22 提交本地仓库 23 提交远程仓库 3 Git下载代码 ...
- 洛谷 P1702 突击考试
P1702 突击考试 题目描述 一日,老师决定进行一次突击考试.已知每个学生都有一个考试能力等级,教室里一共有N个课桌,按照顺序排成一列,每张课桌可以坐两个人,第i张课桌坐的两个人的能力等级为(A[i ...
- 理解Swift中map 和 flatMap对集合的作用
map和flatMap是函数式编程中常见的概念,python等语言中都有.借助于 map和flapMap 函数可以非常轻易地将数组转换成另外一个新数组. map函数可以被数组调用,它接受一个闭包作为參 ...
- [MST] Attach Behavior to mobx-state-tree Models Using Actions
Models are not just a nifty feature for type checking. They enable you to attach behavior to your ac ...
- 使用Qt.labs.settings来存储应用的设置
我在曾经的文章中,讲述了怎样使用U1db及SQLite offline storage API来存储应用的一些状态.在这篇文章中,我将介绍怎样使用Qt.labs.settings来存储应用的状态.更加 ...
- Log4j-----Log4j使用指南
- Linux磁盘分区(一):加入
***********************************************声明************************************************ 原创 ...