Python之迭代器与生成器
一. 迭代器
可以记住遍历位置的对象。迭代器对象会从集合的第一个元素开始访问,直到所有元素被访问。它只能往前访问,不能向后访问。
1. 可迭代对象的概念
像字符串、列表、元祖、集合、字典,我们可以使用for…in…语句进行遍历(或叫迭代)的这样的一个对象
2. 创建迭代器及其使用
创建方式(创建迭代器):ite = iter(可迭代对象)
使用方式(取出迭代器内的值):next(ite)
一次取一个值,直到遇到StopIteration异常
而停止
3. 可迭代的对象iterable和迭代器iterator
使用isinstance() 函数来判别左参数实例是否为右参数对象的子类
- 判断是否为可迭代对象
结果:
- 判断是否为迭代器:
结果
可迭代对象可以组成迭代器,但不属于迭代器。
4. 简单案例
(1)列表迭代器
创建一个列表,通过 iter() 函数来将可迭代对象 list 转化成迭代器,再通过next()函数来逐步遍历迭代器,最后返回异常标识 StopIteration 标识表示遍历结束。
(2)字典迭代器(迭代key值)
5. 用魔法方法自制迭代器
使用__iter__和__next__自制迭代器
代码:
# -*- coding:utf-8 -*-
from collections import Iterable
class MyList(object):
def __init__(self):
self.container = []
def add(self, item):
self.container.append(item)
def __iter__(self):
"""返回一个迭代器"""
myIterator = MyIterator(self)
return myIterator
class MyIterator(object):
"""自定义供上面的可迭代对象使用的一个迭代器"""
def __init__(self, mylist):
self.mylist = mylist
# 去记录当前位置的变量
self.current = 0
def __next__(self):
if self.current < len(self.mylist.container):
item = self.mylist.container[self.current]
self.current += 1
return item
else:
raise StopIteration
def __iter__(self):
return self
mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
for i in mylist:
print(i)
print(isinstance(mylist, Iterable))
# 一个具备了__iter__方法的对象,就是一个可迭代对象
# 可迭代对象通过 __iter__方法,提供一个迭代器
结果:
1
2
3
True
6. 进阶- 用迭代器写斐波那契数列案例
# -*- coding:utf-8 -*-
class FibIterator(object):
def __init__(self, n):
self.num1 = 0
self.num2 = 1
self.n = n
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.n:
num = self.num1
self.num1, self.num2 = self.num2, self.num1 + self.num2
self.current += 1
return num
else:
raise StopIteration
if __name__ == '__main__':
fib = FibIterator(10)
print(fib)
for i in fib:
print(i, end=' ')
结果:
<__main__.FibIterator object at 0x00000235180A1D30>
0 1 1 2 3 5 8 13 21 34
7. for [value] in [iterable] 形式的本质
通过__iter__函数
获得可迭代对象iterable的迭代器,并且调用__next__
方法赋值给value,当值取完后,raise异常。
8. 迭代器的概念及其特点
- 迭代器是python最强大的功能之一,是访问集合元素的一种方式
- 迭代器是一个可以记住遍历位置的对象
- 迭代器从集合的第一个元素开始访问, 直到所有元素被访问完而结束,访问完的标识是出现异常标识StopIteration。它只能往前不能后退
- 迭代器有两个基本方法:
iter()
和next()
- 字符串、列表、元组等可迭代对象 (iterable)都可以用于创建迭代器
- 只要实现了__iter__对象就是可迭代对象,同时实现了__iter__和__next__的是迭代器,并且__next__在迭代完成后应该抛出异常。
二. 生成器
生成器是一类特殊的迭代器
1. 创建生成器及使用
(1). 普通生成器
创建方法:generator = (iterable)
取值方法:next(generator)
生成器类似于列表推导式[ i for i in range(10) ], 不过把中括号 [ ] 换成小括号 ()
,从而变成生成器
简单尝试如下案例:
g = (i for i in range(10))
print(g)
结果:
<generator object <genexpr> at 0x00000242630FE830>
(2). 函数生成器
在函数中添加yield
关键字,该函数就为生成器
2. 用生成器函数写裴波那切数列
yield为生成器,return返回异常值
def fib(n):
current = 0
num1, num2 = 0, 1
while current < n:
num = num1
num1, num2 = num2, num1 + num2
current += 1
yield num
return "done"
F = fib(5)
print(next(F))
print(next(F))
print(next(F))
print(next(F))
print(next(F))
print(next(F))
结果:
0
1
1
2
3
StopIteration: done
同例:
结果:
3. 生成器的概念及其特点
- 在python中使用了yield的函数不是函数,而是生成器(generator)
- 与普通函数不同,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单的理解是:生成器就是一个迭代器
- 在调用生成器运行的过程中,每次遇到 yield 时,函数会暂停并保存当前运行的运行状态、所有信息(类似于断点执行,阻塞、挂起状态),yield后面的值作为返回值返回,并在下一次执行 next() 时从当前位置继续运行(唤醒生成器)
- 调用一个生成器函数,返回的是一个迭代对象