Python中迭代器
迭代是一个动词,它指的是一种操作,在Python中,就是 for 循环。
可迭代对象:可以直接作用于for循环的对象统称为可迭代对象(Iterable)
可以用isinstance()取判断一个对象是否是Iterable对象
可以直接作用于for的数据类型一般分两种
1,集合数据类型,如list,tuple,set,string
2,是generator,包括生成器和带yield的generator function(函数生成器)
特点:
a)访问者不需要关心迭代器内部的结构,仅需通过next()方法或不断去取下一个内容
b)不能随机访问集合中的某个值 ,只能从头到尾依次访问
c)访问到一半时不能往回退
d)便于循环比较大的数据集合,节省内存
e)也不能复制一个迭代器。如果要再次(或者同时)迭代同一个对象,只能去创建另一个迭代器对象
from collections import Iterable #导入包
from collections import Iterator #导入包
print(isinstance([],Iterable)) # True 是可迭代对象
print(isinstance((),Iterable))
print(isinstance({},Iterable))
print(isinstance("",Iterable))
print(isinstance(1,Iterable)) # False
print(isinstance((x for x in range(10)),Iterable))
#(输出) True
True
True
True
False
True
迭代器:
不但可以作用于for循环,换可以被next()函数不断调用并返回下一个值
,直到最后跑出一个StopIteration错误表示无法继续返回下一个值
可迭代对象:可以被next()函数调用并不断返回下一个值得对象称为迭代器(Iterator对象)
可以使用isinstance()函数判断一个对象是否是Iterator
from collections import Iterator #导入包
print(isinstance([],Iterator))
#(输出)False
print(isinstance((),Iterator))
#(输出)False
print(isinstance({},Iterator))
#(输出)False
print(isinstance("",Iterator))
#(输出)False
print(isinstance(1,Iterator))
#(输出)False
print(isinstance((x for x in range(10)),Iterator))
#(输出)True
#(只有最后一个True 因为只有最后一个才为迭代器)
l = (x for x in range(5))
print(next(l))
#(输出)0
print(next(l))
#(输出)1
print(next(l))
#(输出)2
print(next(l))
#(输出)3
print(next(l))
#(输出)4
#print(next(l)) #超过数值报错
#转成迭代器 Iterator对象
a = iter([1,2,3,4,5])
print(next(a))
#(输出)1
print(next(a))
#(输出)2
print(next(a))
#(输出)3
print(isinstance(iter([]),Iterator))
#(输出)True
print(isinstance(iter(()),Iterator))
#(输出)True
print(isinstance(iter({}),Iterator))
#(输出)True
print(isinstance(iter(""),Iterator))
#(输出)True
迭代与按下标访问数组最大的不同是,后者是一种具体的迭代实现方式,而前者只关心迭代结果,根本不关心迭代内部是如何实现的。
dict的迭代器
把dict转换成一个包含所有value的list,我们迭代的就是 dict的每一个 value:
d = { 'A': 55, 'B':65, 'C': 79 }
print (d.values())
#(输出)dict_values([55, 65, 79])
for v in d.values():
print (v)
#(输出) 55
65
79
一个 for 循环中,同时迭代 key和value:
d = { 'A': 55, 'B': 65, 'C': 79 }
print (d.items())
#(输出)dict_items([('A', 55), ('B', 65), ('C', 79)])
反向迭代reversed():
使用内置的reversed()函数
a = [1, 2, 3, 4]
for x in reversed(a):
print(x)
#(输出) 4
3
2
1
enumerate对象通过for循环迭代一次后就不能再被迭代:
这是因为enumerate是一个迭代器;
迭代器是一次性消耗品,当循环以后就空了。
不能再次使用;通过深拷贝可以解决;
e = enumerate([1,2,3])
for x,y in e:
print(x,y)
#(输出) 0 1
1 2
2 3
for x,y in e:
print(x,y) #再次输入时,输出为空
#(输出)
深拷贝:
import copy
e = enumerate([1,2,3])
e_deepcopy = copy.deepcopy(e)
for x,y in e:
print(x,y)
#(输出) 0 1
1 2
2 3
for x,y in e_deepcopy:
print(x,y)
#(输出) 0 1
1 2
2 3
生成器(generator)
yield 的函数在 Python 中被称之为 generator(生成器)
Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
它特殊的地方在于函数体中没有return关键字,函数的返回值是一个生成器对象。当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。
import itertools
def fib():
prev, curr = 0, 1
while True:
yield curr
prev, curr = curr, curr + prev
f = fib()
print(list(itertools.islice(f, 0, 10)))
#(输出)[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
相比其它容器对象它更能节省内存和CPU,当然它可以用更少的代码来实现相似的功能。
def something():
result = []
for ... in ...:
result.append(x)
return result
#转换为:
def iter_something():
for ... in ...:
yield x