迭代(Iteration),迭代器协议,迭代器(Iterator),可迭代对象(Iterable)

迭代(Iteration):用简单的话讲,它就是从某个地方(比如列表)取出一个元素的过程。当我们使用一个循环来遍历时,这个过程本身就叫迭代。

例如:

1
2
3
li = ['a','b','c','d']
for item in li:
    print("迭代列表li:",item)

执行以上程序会输出如下结果:

1
2
3
li = ['a','b','c','d']
for item in li:
    print("迭代列表li:",item)

迭代器协议:对象需要提供iter方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。

迭代器(Iterator):任何对象,如果它的类有next 方法和iter方法,next方法返回下一个元素,iter方法返回迭代器自己本身。

可迭代对象(Iterable):实现了迭代器协议对象。list、tuple、set、dict都是Iterable(可迭代对象),但不是Iterator(迭代器对象)。但可以使用内建函数iter(),转换成Iterator(可迭代器对象)。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
l = ['a','b','c','d']
t = ('a','b','c','d')
s = {'a','b','c','d'}
d = {1:'a',2:'b',3:'c',4:'d'}

iter_l = iter(l) # 列表转换为Iterator
print(iter_l)

iter_t = iter(t) # 元组转换为Iterator
print(iter_t)

iter_s = iter(s) # 集合转换为Iterator
print(iter_s)

iter_d = iter(d) # 字典转换为Iterator
print(iter_d)

执行以上程序会输出如下结果:

1
2
3
4
<list_iterator object at 0x7f1ea443a8d0>
<tuple_iterator object at 0x7f1ea443a908>
<set_iterator object at 0x7f1ea4439bd0>
<dict_keyiterator object at 0x7f1ea4432bd8>

for item in Iterable循环的本质就是先通过iter()函数获取可迭代对象的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
l = ['a','b','c','d']
iter_l = iter(l) #列表转换为Iterator

#迭代列表对象
for item in l:
    print("迭代列表l:",item)

#迭代列表Iterator对象,和迭代列表是一样的。
for item in iter_l:
    print("迭代列表Iterator iter_l:",item)

执行以上程序会输出如下结果:

1
2
3
4
5
6
7
8
迭代列表l: a
迭代列表l: b
迭代列表l: c
迭代列表l: d
迭代列表Iterator iter_l: a
迭代列表Iterator iter_l: b
迭代列表Iterator iter_l: c
迭代列表Iterator iter_l: d

除了使用for in语法,还可以调用迭代器的next()方法来迭代数据。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
listArray=[1,2,3] # 定义一个list
iterName=iter(listArray) # 使用iter()函数
print(iterName)  # 结果:是一个列表list的迭代器
<list_iterator object at 0x0000017B0D984278>
print(next(iterName))  # 结果:1
print(next(iterName))  # 结果:2
print(next(iterName))  # 结果:3
print(next(iterName)) #没有迭代到下一个元素,直接抛出异常
Traceback (most recent call last):
File "Test07.py", line 32, in <module>
StopIteration

列表的键值对迭代

Python内置的enumerate函数可以以键值对的形式迭代列表。

例如:

1
2
3
l = ['a','b','c','d']
for i, value in enumerate(l):
    print("列表l的键值对迭代:",i,value)

执行以上程序会输出如下结果:

1
2
3
4
列表l的键值对迭代: 0 a
列表l的键值对迭代: 1 b
列表l的键值对迭代: 2 c
列表l的键值对迭代: 3 d

字典迭代

默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
d = {1:'a',2:'b',3:'c',4:'d'}
#字典默认迭代 key迭代
for item in d:
    print("迭代字典d的key:",item)

#字典键值迭代 value迭代
for item in d.values():
    print("迭代字典d的value:",item)

#字典键值对迭代 value迭代
for item_key,item_value in d.items():
    print("迭代字典d的键值对:",item_key,item_value)

执行以上程序会输出如下结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
迭代字典d的key: 1
迭代字典d的key: 2
迭代字典d的key: 3
迭代字典d的key: 4
迭代字典d的value: a
迭代字典d的value: b
迭代字典d的value: c
迭代字典d的value: d
迭代字典d的键值对: 1 a
迭代字典d的键值对: 2 b
迭代字典d的键值对: 3 c
迭代字典d的键值对: 4 d

字节,字符串迭代

由于字节对象,字符串对象也是可迭代对象,因此,也可以作用于for循环:

例如:

1
2
3
4
5
6
s = "hello"
for item in s:
    print("迭代字符串s:",item)
b = b"hello"
for item in b:
    print("迭代字节b:",item)

执行以上程序会输出如下结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
迭代字符串s: h
迭代字符串s: e
迭代字符串s: l
迭代字符串s: l
迭代字符串s: o
迭代字节b: 104
迭代字节b: 101
迭代字节b: 108
迭代字节b: 108
迭代字节b: 111

判断是否是可迭代对象

通过collections模块的Iterable类型判断是否是可迭代对象。Iterator类型判断是否是迭代器对象。
isinstance()函数判断对象是否是某类型的实例。返回值True代表是某类的实例,False代表不是某类的实例。

例如:

1
2
3
4
5
6
7
8
9
from collections import Iterable
from collections import Iterator

s = "hello"
b = b"hello"
print(isinstance(s, Iterable)) #字符串str是Iterable
print(isinstance(s, Iterator)) #字符串str不是Iterator
print(isinstance(b, Iterable)) #字节bytes是Iterable
print(isinstance(b, Iterator)) #字节bytes不是Iterator

执行以上程序会输出如下结果:

1
2
3
4
True
False
True
False

为什么list、dict、str,bytes等数据类型不是Iterator?
Iterator对象表示的是一个数据流,是有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。而list、dict、str,bytes等数据类型都实现了len()函数,知道其长度大小。所以不是Iterator对象。


转载请注明本网址。