Python——iter函数的用法


整体说明

  • 在 Python 里,iter() 函数主要用于生成迭代器
  • 迭代器用于遍历可迭代对象(像列表、元组、字典这样的),能逐个获取对象里的元素
  • 用法可总结如下:
    • iter() 函数的主要作用是把可迭代对象转变为迭代器
    • 迭代器通过 next() 函数来获取下一个元素
    • 可以通过自定义类并实现 __iter__()__next__() 方法来自定义迭代器
    • 使用 StopIteration 异常或者设置哨值能够终止迭代

iter()函数的基本用法

  • 函数用法:

    1
    iter(iterable)
    • 这里的 iterable 可以是列表、元组、字符串、集合等可迭代对象
  • 示例:遍历列表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    my_list = [1, 2, 3, 4, 5]
    my_iter = iter(my_list)

    # # 错误用法,会抛出异常
    # for i in range(10):
    # print(next(my_iter)) # 依次输出:1,2,3,4,5,第6次调用时直接抛出异常 StopIteration

    # 正确用法
    for i in my_iter:
    print(i) # 依次输出:1,2,3,4,5 然后停止

自定义迭代器(无终止迭代)

  • 借助 iter() 函数,还能自定义迭代器,这需要在类中实现 __iter__()__next__() 方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class MyNumbers:
    def __iter__(self):
    self.a = 1
    return self

    def __next__(self):
    x = self.a
    self.a += 1
    return x

    myclass = MyNumbers()
    myiter = iter(myclass)

    print(next(myiter)) # 输出:1
    print(next(myiter)) # 输出:2
    print(next(myiter)) # 输出:3

自定义迭代器(终止迭代)

  • 在自定义迭代器时,可以使用 StopIteration 异常来终止迭代
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class MyNumbers:
    def __iter__(self):
    self.a = 1
    return self

    def __next__(self):
    if self.a <= 3:
    x = self.a
    self.a += 1
    return x
    else:
    raise StopIteration

    myclass = MyNumbers()
    myiter = iter(myclass)

    for x in myiter:
    print(x) # 依次输出1,2,3后停止(注意程序是自然退出的,不会抛出异常)

附录:Iterable 和 Iterator 的区别

  • 可迭代对象(Iterable) :任何可以被 iter() 函数调用并返回一个迭代器的对象
    • 常见例子:列表(list)、元组(tuple)、字符串(str)、字典(dict)、集合(set)等
    • 可以用 for 循环遍历,不存储迭代状态(即每次调用 iter() 都会生成一个新的迭代器)
    • 可以被多次迭代(每次都是新的迭代器)
  • 迭代器(Iterator) :实现了 __next__() 方法和 __iter__() 方法的对象
    • 常见例子:由 iter() 函数返回的对象、生成器(generator)等
    • 有“状态”,记录当前迭代位置
    • 调用 next() 方法会返回下一个元素,直到耗尽后抛出 StopIteration
    • 只能迭代一次(无法重置,耗尽后失效)
    • __iter__() 方法返回自身(所以迭代器也是一种可迭代对象)
  • 特别说明:DataLoader 本身是一个可迭代对象(iterable),而非一次性迭代器(iterator)

附录:特别说明 iter() 的第二个参数

  • iter() 函数还有一种不太常见的用法,就是接收两个参数
    • 第一个参数得是个可调用对象(像函数)
    • 第二个参数是哨值
  • 当可调用对象返回的值等于哨值时,迭代就会停止
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def my_function():
    value = input("请输入内容(输入 'q' 结束):")
    return value

    # 创建迭代器,当输入 'q' 时停止
    my_iter = iter(my_function, 'q')

    for value in my_iter:
    print(f"你输入的是:{value}")

    # 请输入内容(输入 'q' 结束):123
    # 你输入的是:123
    # 请输入内容(输入 'q' 结束):q

附录:for 循环和 __iter__ 函数的用法

  • for i in x 循环中,x.__iter__() 只会被调用一次 ,且该方法的返回值必须是一个 Iterator(迭代器)
    • 这属于 Python 迭代协议(Iteration Protocol)的核心要求
  • __iter__ 的调用 1 次后,循环的所有迭代过程,都基于 __iter__ 返回的同一个迭代器
  • __iter__ 的返回值要求:必须返回一个实现了迭代器协议的对象(即同时具有 __iter__()__next__() 方法的对象)
    • 可迭代对象的 __iter__:“生产迭代器”(返回新的迭代器实例);
    • 迭代器的 __iter__:“暴露自己”(返回自己,因为自己就是 “干活的”)
    • 迭代器的 __next__(),真正用于返回下一个元素
  • 支持 for 循环的对象,一定是具有 __iter__() 函数的

原理拆解:for 循环的执行流程

  • for i in x 的底层逻辑完全遵循迭代协议,步骤如下:
    • 1)调用 x.__iter__(),获取一个迭代器对象(记为 it);
    • 2)反复调用 it.__next__(),每次返回的结果赋值给 i,执行循环体;
    • 3)当 it.__next__() 抛出 StopIteration 异常时,循环捕获该异常并正常终止(不会暴露给用户)
  • 注:整个过程中,x.__iter__() 只在第一步执行一次,后续所有迭代都依赖第一步返回的那个 it 迭代器