迭代器与可迭代对象
1、定义:
可迭代对象:大部分容器如 list,truples,str,sets是可迭代对象,但是他们不是迭代器。可迭代对象实现了__iter__方法,返回一个迭代器,或者使用iter(“可迭代对象”)返回一个迭代器。
迭代器:迭代器提供了一种不依赖索引取值的方式,这样可以遍历没有索引的可迭代对象,比如字典、集合、文件等等,加载这一个元素至内存中随后释放,相比之下更节省内存,但是我们没有办法获取迭代器的长度,而且只能往后依次取值。遍历的方法使用next(“迭代器”)
2、代码示例
d={'a':1,'b':2,'c':3}
s = d.__iter__() #s是一个迭代器
p = iter(“可迭代对象”) #p是一个迭代器
#遍历迭代器
next(p)
next(p)
3、for循环
在for循环中,Python将自动调用工厂函数iter()获得迭代器,自动调用next()获取元素,还完成了检查StopIteration异常的工作。如下
a = (1, 2, 3, 4)
for key in a:
print key
首先python对关键字in后的对象调用iter函数迭代器,然后调用迭代器的next方法获得元素,直到抛出StopIteration异常。
4、自定义一个迭代器:
class Fibs:
def __init__(self): #初始化
self.a = 0
self.b = 1
def __next__(self): #获取下一个条目
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self): #返回迭代器
return self
fibs = Fibs() #产生一个对象
for f in fibs: #迭代
if f > 5:
break
print(f)
>>>8
next(fibs)
>>>13
next(fibs)
>>>21
生成器
1)创建生成器
在一个一般函数中使用yield关键字,可以实现一个最简单的生成器,此时这个函数变成一个生成器函数。
yield与return返回相同的值,区别在于return返回后,函数状态终止,而yield会保存当前函数的执行状态,在返回后,函数又回到之前保存的状态继续执行。
2)为何使用生成器
内存使用更加高效。比如列表是在建立的时候就分配所有的内存空间,而生成器仅仅是需要的时候才会产生。如果我们要读取并使用的内容远远超过内存,但是需要对所有的流中的内容进行处理,那么生成器是一个很好的选择。
3)生成器函数的特点
ü 生成器函数包含一个或者多个yield
ü 当调用生成器函数时,函数将返回一个对象,但是不会立刻向下执行
ü 生成器中__iter__()和__next__()方法等是自动实现的,所以我们可以通过next()方法对对象进行迭代
ü 一旦函数被yield,函数会暂停,控制权返回调用者
ü 局部变量和它们的状态会被保存,直到下一次调用
ü 函数终止的时候,StopIteraion会被自动抛出
4)生成器函数构造示例
l 构造循环生成器
逆序yield出对象的元素
def a(my_str):
length=len(my_str)
for i in range(length-1,-1,-1):
yield my_str[i]
for char in a("hello"):
print(char)
l 生成器表达式
a=(x for x in range(10))
b=[x for x in range(10)]
# 这是错误的,因为生成器不能直接给出长度
# print("length a:",len(a))
# 输出列表的长度
print("length b:",len(b))
b=iter(b)
# 二者输出等价,不过b是在运行时开辟内存,而a是直接开辟内存
print(next(a))
print(next(b))