python | 迭代器

0x00 可迭代对象与迭代器

  • 可迭代对象是指实现了__iter__()方法的对象。实现了__getitem__()方法的对象也可以被迭代。

  • 迭代器是指实现了__next__()方法的对象。迭代器实现了__iter__()方法,但其返回自身

  • __iter__()方法返回一个迭代器对象。

  • __next__()方法返回迭代器的下一个值。

1
2
3
4
5
6
7
8
9

'''
list是一个可迭代对象,其iter方法返回一个迭代器,其没有next方法
list的迭代器是list_iterator, 其iter方法返回自身, next方法返回下一个值
'''
a = [1,2,3] # type(a) == <class 'list'>
b = a.__iter__() # type(b) == <class 'list_iterator'>
next(a) # 抛出异常 TypeError: 'list' object is not an iterator
c = b.__iter__() # type(c) == <class 'list_iterator'> 迭代器的iter返回自身

总结:迭代器必须有iter方法,不一定有next方法;可迭代对象必须有iter方法和next方法。可迭代对象和迭代器可以是同一个对象,但不一定是。
可迭代对象可以通过iter()函数转换为迭代器。

0x01 迭代器与生成器的区别

  • 迭代器是一个对象,它实现了__iter__()__next__()方法。

  • 生成器是一个特殊的迭代器,它使用yield关键字由函数来创建,产生一个生成器对象。

    生成器对象实现了如下方法:

    • iter():返回自身,使其成为可迭代对象。
    • next():每次调用返回下一个 yield 的值,直到结束抛出 StopIteration。
    • 还实现了 send(value)、throw(type, value=None, traceback=None)、close() 等方法,用于高级生成器控制。

0x02 可使用下标索引的对象

可通过下标索引的对象是实现了__getitem__()方法的对象。常见的可使用下标索引的对象包括: * 列表(list) * 元组(tuple) * 字典(dict) * 字符串(str)

可以使用list()或者tuple()函数将可迭代对象转换为列表或元组,从而可以使用下标索引访问元素。

常见的需要转化的例子有

1
2
3
4
5
6
7
gen = (x * x for x in range(5))  # 生成器对象,不能直接用下标访问
lst = list(gen) # 转换为列表后可以用下标访问
print(lst[2]) # 输出 4

s = set([1, 2, 3]) # 集合是可迭代对象,但不能用下标访问
lst2 = list(s) # 转换为列表后可以用下标访问
print(lst2[0])

0x03 for循环原理

for循环会调用可迭代对象的__iter__()方法获取迭代器,然后在每次循环中调用迭代器的__next__()方法获取下一个值,直到抛出StopIteration异常为止。

如果可迭代对象没有实现__iter__()方法,for循环会尝试使用__getitem__()方法来获取元素。从索引0开始,依次获取元素,直到抛出IndexError异常为止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class MyIterable:
def __init__(self, data):
self.data = data

def __iter__(self):
print("Creating iterator")
self.index = 0
return self

def __next__(self):
print("Getting next item")
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration

def __getitem__(self, index):
print(f"Accessing item at index {index}")
if index < len(self.data):
return self.data[index]
else:
raise IndexError("Index out of range")

for item in MyIterable([1, 2, 3]):
print(item)

"""Output1:
Creating iterator
Getting next item
1
Getting next item
2
Getting next item
3
Getting next item
"""

# 注释掉iter方法
"""Output2:
Accessing item at index 0
1
Accessing item at index 1
2
Accessing item at index 2
3
Accessing item at index 3

python | 迭代器
https://jfsas.github.io/2025/08/03/python-迭代器与可迭代方法以及for循环原理/
作者
JFSAS
发布于
2025年8月3日
许可协议