概述
一、迭代器(iterator)
在Python中,for循环可以用于Python中的任何类型,包括列表、元组,字符串等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器 迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。
使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。
比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:
for line in open("test.txt").readlines():
print line
这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。
利用file的迭代器,我们可以这样写:
for line in open("test.txt"): #use file iterators
print line
这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。
迭代器协议
迭代器协议指的是容器类需要包含一个特殊方法 如果一个容器类提供了__iter__()方法,并且该方法能返回一个能够逐个访问容器内所有元素的迭代器,则我们说该容器类实现了迭代器协议。 python中的迭代器协议和for循环是紧密相连的
for x in something:
print(x)
Python 处理 for 循环时,首先会调用内建函数 iter(something),它实际上会调用 something.iter(),返回 something 对应的迭代器。而后,for 循环会调用内建函数 next(),作用在迭代器上,获取迭代器的下一个元素,并赋值给 x。此后,Python 才开始执行循环体
二、生成器(constructor)
生成器函数在Python中与迭代器协议的概念联系在一起。简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。函数也许会有个return语句,但它的作用是用来yield产生值的。
不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效
def g(n):
for i in range(n):
yield i **2
for i in g(5):
print (i)
要了解他的运行原理,我们来用next方法看看:
t = g(5)
t.__next__()
0
t.__next__()
1
t.__next__()
4
t.__next__()
9
t.__next__()
16
t.__next__()
Traceback (most recent call last):
File “”, line 1, in StopIteration
在运行完5次next之后,生成器抛出了一个StopIteration异常,迭代终止。
三、yield表达式 如果一个函数包含了yield表达式,那么这个函数就是一个生成器函数 实际上,yield表达式,只能判断函数是不是生成器函数 与普通函数不同,生成器函数被调用后,其函数体内的代码并不会立即执行,而是返回一个生成器(generator-iterator)。当返回的生成器调用成员方法时,相应的生成器函数中的代码才会执行。
def square():
for i in range(10):
yield i
square_gen=square()
for x in square_gen:
print(x)
前面说到,for 循环会调用 iter() 函数,获取一个生成器;而后调用 next() 函数,将生成器中的下一个值赋值给 x;再执行循环体。因此,上述 for 循环基本等价于:
geniter=square_gen.__iter__
while True:
x=geniter.__next__()
print(x) #1
geniter.send(3) #4
geniter.send(10) #14
注意到,square 是一个生成器函数;作为它的返回值,square_gen 已经是一个迭代器;迭代器的 iter() 返回它自己。因此 geniter 对应的生成器函数,即是 square。
每次执行到 x = geniter.__ next __() 时,square 函数会从上一次暂停的位置开始,一直执行到下一个 yield 表达式,将 yield 关键字后的表达式列表返回给调用者,并再次暂停。注意,每次从暂停恢复时,生成器函数的内部变量、指令指针、内部求值栈等内容和暂停时完全一致。 生成器的方法 生成器有一些方法。调用这些方法可以控制对应的生成器函数;不过,若是生成器函数已在执行过程中,调用这些方法则会抛出 ValueError 异常。
generator.next():从上一次在 yield 表达式暂停的状态恢复,继续执行到下一次遇见 yield 表达式。当该方法被调用时,当前 yield 表达式的值为 None,下一个 yield 表达式中的表达式列表会被返回给该方法的调用者。若没有遇到 yield 表达式,生成器函数就已经退出,那么该方法会抛出 StopIterator 异常。 generator.send(value):和 generator.next() 类似,差别仅在与它会将当前 yield 表达式的值设置为 value。 generator.throw(type[, value[, traceback]]):向生成器函数抛出一个类型为 type 值为 value 调用栈为 traceback 的异常,而后让生成器函数继续执行到下一个 yield 表达式。其余行为与 generator.next() 类似。 generator.close():告诉生成器函数,当前生成器作废不再使用。 举例和说明 如果你看不懂生成器函数 如果你还是不太能理解生成器函数,那么大致上你可以这样去理解。
在函数开始处,加入 result = list(); 将每个 yield 表达式 yield expr 替换为 result.append(expr); 在函数末尾处,加入 return result。
使用 send() 方法与生成器函数通信:
def func():
x = 1
while True:
y = (yield x)
x += y
geniter = func()
geniter.__next__() #1
geniter.send(3) #4
geniter.send(12) #16
此处,生成器函数 func 用 yield 表达式,将处理好的 x 发送给生成器的调用者;与此同时,生成器的调用者通过 send 函数,将外部信息作为生成器函数内部的 yield 表达式的值,保存在 y 当中,并参与后续的处理。
这一特性是使用 yield 在 Python 中使用协程的基础
最后
以上就是顺心柜子为你收集整理的python3迭代器是什么_Python3中的迭代器、生成器和的全部内容,希望文章能够帮你解决python3迭代器是什么_Python3中的迭代器、生成器和所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复