迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式,是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
递归和迭代的区别:递归是内部指针等待的一个过程,需要一直嵌套得到结果,而迭代是遍历的过程,前面的过程结束后可以进行下一项,不需要等待
字符串,列表或元组对象都可用于创建迭代器
for循环实际上实现了__iter__()方法生成了一个迭代器对象,然后一步步next(for循环实际上就是一步步next) 直到报错并返回 , 是一个完整的过程
对于序列如此,对于字典和文件等也是如此,统一生成迭代器来循环
所以,凡是能被for循环的对象内部都有一个__iter__()方法:如dict list set tuple 内部都有__iter__方法
for i in file: 所以读取文件用for,文件生成迭代器是一行行读,前面读完的行内存就回收掉了,不占用内存
next()内置函数实际上就是实现对象内部的__next__()方法,效果一样
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
print (next(it)) # 输出迭代器的下一个元素
把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
next() 方法(Python 2 里是 next())会返回下一个迭代器对象。
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 20:
x = self.a
self.a += 1
return x
else:
raise StopIteration
myclass = MyNumbers()
myiter = iter(myclass)
for x in myiter:
print(x)
生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator),或者说 一边循环一边计算的机制,称为生成器:generator
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行,调用一个生成器函数,返回的是一个迭代器对象。
为什么要用生成器?
列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。
如:仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。如果列表元素按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
简单一句话:我又想要得到庞大的数据,又想让它占用空间少,那就用生成器!
生成器的工作原理
(1)生成器(generator)能够迭代的关键是它有一个next()方法 工作原理就是通过重复调用next()方法,直到捕获一个异常。
(2)带有 yield 的函数不再是一个普通函数,而是一个生成器generator。可用next()调用生成器对象来取值。next 两种方式 t.next() | next(t)。可用for 循环获取返回值(每执行一次,取生成器里面一个值)
(基本上不会用next()来获取下一个返回值,而是直接使用for循环来迭代)。
(3)yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield的下一条语句开始执行。
(4).send() 和next()一样,都能让生成器继续往下走一步(下次遇到yield停),但send()能传一个值,这个值作为yield表达式整体的结果
——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10
import sys
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), end=" ")
except StopIteration:
sys.exit()
1 #encoding:UTF-8
2 def yield_test(n):
3 for i in range(n):
4 yield call(i)
5 print("i=",i)
6 print("Done.")
7
8 def call(i):
9 return i*2
10
11 for i in yield_test(5):
12 print(i,",")
>>>
0 ,
i= 0
2 ,
i= 1
4 ,
i= 2
6 ,
i= 3
8 ,
i= 4
Done.
>>>