Python: next() function
我正在从一本书中学习python,我遇到了这个例子:
1 2 3 4 5 6 | M = [[1,2,3], [4,5,6], [7,8,9]] G = (sum(row) for row in M) # create a generator of row sums next(G) # Run the iteration protocol |
因为我是一个绝对的初学者,并且作者没有提供任何关于示例或next()函数的解释,所以我不理解代码在做什么。
表达式
声明
1 2 3 4 5 6 7 8 9 10 11 | >>> M = [[1,2,3], ... [4,5,6], ... [7,8,9]] >>> >>> G = (sum(row) for row in M) # create a generator of row sums >>> next(G) # Run the iteration protocol 6 >>> next(G) 15 >>> next(G) 24 |
参见:
- 发电机文件
- 有关产量表达式的文档(包含有关生成器的一些信息)
如果你已经走了那么远,那么你应该已经知道了一个公共for语句是如何工作的。
以下声明:
1 | for row in M: print row |
将m视为3行(子序列)的序列,每行由3个项目组成,并迭代m,在矩阵上输出每行:
1 2 3 | [1, 2, 3] [4, 5, 6] [7, 8, 9] |
你知道的,嗯…
您可以将生成器看作是循环中的一些语法甜头。忘记sum()调用,然后在空闲时键入如下内容:
1 2 3 | G = (row for row in M) print G for a in G: print a |
可以看到,生成器不能直接表示为文本,而不仅仅是序列。但是,可以像序列一样迭代生成器。
然后您会发现一些很大的差异,但基本上您可以使用生成器,而不仅仅返回序列中每个项的值,而是返回任何表达式的结果。在本教程的示例中,表达式是sum(row)。
尝试以下操作,看看会发生什么:
1 2 3 4 | G = ("("+str(row[2])+";"+str(row[1])+";"+str(row[0])+")" for row in M) G.next() G.next() G.next() |
要了解此代码如何工作,您需要了解:
1)不可识别对象?
2)迭代器?
3)迭代协议
4)发电机?
5)发电机如何工作?
让我来看看这些:
iterable:iterable是python中定义了iter或getitem方法的任何对象,该方法返回迭代器或可以获取索引。基本上是我们可以在其上运行循环的对象。如:
1 2 | >>> for i in [1,2,3]: print(i) |
一二三
这里我们将列表作为一个不可重复的对象,它的项可以使用索引进行索引和检索。
1 2 | >>> for i in {x:1,y:2}: print(x) |
XY
在这里,我们将字典作为iterable对象,循环其键。
迭代器:迭代器是python中定义了next(python2)或next方法的任何对象。就是这样。这是一个迭代器。
迭代协议:内置函数iter接受一个iterable对象并返回一个迭代器。
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> x = iter([1, 2, 3]) >>> x <listiterator object at 0x1004ca850> >>> x.next() 1 >>> x.next() 2 >>> x.next() 3 >>> x.next() Traceback (most recent call last): File"<stdin>", line 1, in <module> StopIteration |
生成器:生成器是迭代器,但只能对它们进行一次迭代。这是因为它们不将所有值存储在内存中,而是动态生成值。
例如:
1 2 3 4 5 | def yrange(n): i = 0 while i < n: yield i i += 1 |
每次执行yield语句时,函数都会生成一个新值。
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> y = yrange(3) >>> y <generator object yrange at 0x401f30> >>> y.next() 0 >>> y.next() 1 >>> y.next() 2 >>> y.next() Traceback (most recent call last): File"<stdin>", line 1, in <module> StopIteration |
所以生成器也是一个迭代器。
注意:每次调用next()时,它都会从停止的位置恢复(它会记住所有的数据值以及上次执行的语句)。另一个关键特性是本地变量和执行状态在调用之间自动保存。
让我们用示例来理解这一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | >>> def foo(): print"begin" for i in range(3): print"before yield", i yield i print"after yield", i print"end" >>> f = foo() >>> f.next() begin before yield 0 0 >>> f.next() after yield 0 before yield 1 1 >>> f.next() after yield 1 before yield 2 2 >>> f.next() after yield 2 end Traceback (most recent call last): File"<stdin>", line 1, in <module> StopIteration |
现在我们来谈谈你的问题:
1 2 3 4 5 6 | M = [[1,2,3], #M is iterable object [4,5,6], [7,8,9]] G = (sum(row) for row in M) # creates a generator of row sums next(G) # Run the iteration protocol |