实现迭代器协议的对象支持遍历
for x in [1,2,3]: #列表
...: print(x)
...:
1
2
3
for x in (1,2,3): #元组
...: print(x)
...:
1
2
3
d = {'a':1,'b':2} #字典表
for k in d:
...: print(k)
...:
a
b
f = open('hello.txt') #文件本身也是迭代器对象,不调用读方法也能直接遍历
for line in f:
...: print(line, end = '')
...:
Hello world
Python
迭代器对象与可迭代对象
f = open('hello.txt')
iter(f) is f
Out[14]: True
f.__next__()
Out[16]: 'Hello world\n'
f.__next__()
Out[18]: 'Python\n'
l = ['a','b','c']
iter(l) is l
Out[21]: False
l.__next__()
AttributeError: 'list' object has no attribute '__next__'
i = iter(l)
i.__next__()
Out[25]: 'a'
i.__next__()
Out[26]: 'b'
i.__next__()
Out[27]: 'c'
文件和列表都能直接用for循环遍历,因为它们都实现了_next_()方法,使用时无需将整个文件或列表读入内存,而是一个元素接下一个元素遍历。但它们之间还有区别,文件属于迭代器对象,已经直接实现了_next_()方法;而列表属于可迭代对象,一开始并没实现_next_()方法,而是在使用for循环遍历时通过iter()方法实现_next_()方法。
使用迭代遍历操作列表
l = [1,2,3]
res = []
i = iter(l)
while True:
...: try:
...: x = res.append(next(i)**2)
...: except StopIteration:
...: break
...:
res
Out[36]: [1, 4, 9]
# result = [x**2 for x in l]使用列表推导,效率更高
字典表的视图也是可迭代对象
emp = {'name':'Tom','age':20,'salary':8000.00}
emp.keys() #为可迭代对象而非列表,更省内存
Out[38]: dict_keys(['name', 'age', 'salary'])
emp.items()
Out[39]: dict_items([('name', 'Tom'), ('age', 20), ('salary', 8000.0)])
keys = emp.keys()
iter(keys) is keys
Out[41]: False
i = iter(keys) #创建迭代器对象
i.__next__()
Out[43]: 'name'
i.__next__()
Out[44]: 'age'
next(i)
Out[45]: 'salary'
内置可迭代对象
r = range(1,20) #range()返回的对象支持循环遍历及推导,但并非列表,属于可迭代对象
type(r)
Out[47]: range
iter(r) is r
Out[48]: False
i = iter(r)
i.__next__()
Out[50]: 1
i.__next__()
Out[51]: 2
next(i)
Out[52]: 3
result = zip([1,2,3],['a','b','c']) #zip()返回的也属于可迭代对象
result
Out[54]: <zip at 0x20d981fe708>
for x in result:
...: print(x)
...:
(1, 'a')
(2, 'b')
(3, 'c')
result = zip([1,2,3],['a','b','c'])
iter(result) is result
Out[58]: True
result.__next__()
Out[59]: (1, 'a')
类似range()、zip()返回可迭代对象的还有map()、filter(),比直接返回列表更节省内存。