可迭代对象

迭代器类

一个迭代器类必须实现以下两个方法:

  • __iter__():返回迭代器对象本身(即 self)。
  • __next__():返回序列中的下一个元素。如果没有更多元素,抛出 StopIteration 异常。
class MyRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start < self.end:
            current = self.start
            self.start += 1
            return current
        else:
            raise StopIteration

迭代器对象

顾名思义就是迭代器类的实例,还是上面的迭代器类举例

Python 内置函数 next() 可以传入一个迭代器对象,会自动调用 __next()__ 函数

my_range = MyRange(1, 10)  # my_range 就是一个迭代器对象
print(next(my_range))  # 输出1
print(next(my_range))  # 输出2
print(next(my_range))  # 输出3

可迭代对象

必须有 __iter__() 方法,这个方法返回一个迭代器对象

class MyRange:  # 迭代器类
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.start < self.end:
            current = self.start
            self.start += 1
            return current
        else:
            raise StopIteration

class MyRange2:  
    def __iter__(self): 
        return MyRange(0, 5)  # 返回一个迭代器对象

for x in MyRange2():  # MyRang2() 就是一个可迭代对象
    print(x)

for 循环本质

  1. 获取迭代器对象(如果是可迭代对象,就先获取其迭代器对象)
  2. 反复调用 next() 函数,内部会调 __next()__ 方法获取下一个元素
  3. 捕获 StopIteration 异常,跳出循环
for x in MyRange(5, 10):
    print(x)  # 输出 5,6,7,8,9

生成器对象

  • 函数里面有 yield 就是生成器对象(yield 把函数变成了一个生成器对象)
  • 调用该函数不会立即执行其中代码,而是返回一个生成器对象
  • 当作为参数传入 next() 时:每次会从上次暂停的地方继续执行函数,直到遇到 yield,返回值并再次暂停
from collections.abc import Iterable

def gen_fun():
    yield 1  # 第一次调用 next() 返回1 并暂停
    yield 2  # 第二次调用 next() 返回2 并暂停
    print("hello world")
    yield 3  # 第三次调用 next() 输出 hello world 并返回3,然后暂停

gen = gen_fun()
print(isinstance(gen, Iterable))  # 输出 True。gen 是否是可迭代对象
print(hasattr(gen, '__iter__'))  # 输出 True。gen 是否具有 __iter__ 方法
print(hasattr(gen, '__next__'))  # 输出 True。gen 是否具有 __next__ 方法
print(next(gen))  # 输出 1
print(next(gen))  # 输出 2
print(next(gen))  # 输出3(会先打印 hello world)
print(next(gen))  # 报错。函数已经执行完了(没有下一个元素了),因为也是迭代器对象,所以会抛出 StopIteration

生成器应用1

def read_large_file(file_path):
    with open(file_path, 'r') as file:
        for line in file:
            yield line.strip()  #  strip() 去除前后的空格

# 逐行读取大文件
file_gen = read_large_file('large_file.txt')
for line in file_gen:
    print(line)

生成器应用2

def gen_function():
    i = 2
    yield i  # 质数从 2 开始
    while True:
        i += 1
        for j in range(2, i):  # 循环 2 - i(比如当前是 4,需要判断2到4之间的数是否能被 4 整除)
            if (i % j) == 0:  # 如果能整除说明不是质数,就跳出循环
                break
        else:  # 没有 break 才会走这里,没 break 说明之间的数都不能整除,当前值就是质数
            yield i

if __name__ == '__main__':
    gen = gen_function()
    for i in range(20):  # 连续生成 20 个质数
        print(next(gen))

总结

  1. 迭代器对象有 __iter__()__next__() 两个方法
  2. 可迭代对象只有 __iter__() 一个方法
  3. 迭代器对象也是可迭代对象,反之不成立
  4. 元组、列表、字典、字符串 都是可迭代对象
  5. 生成器对象是惰性计算,每次调用才返回下一个对象,所以比较节省内存,也是可迭代对象
posted @ 2025-03-15 16:04  CyrusHuang  阅读(98)  评论(0)    收藏  举报