page contents

迭代器与生成器:Python中的流式数据处理双雄!

本文讲述了迭代器与生成器:python中的流式数据处理双雄!具有很好的参考价值,希望对大家有所帮助。一起跟随好学星城小编过来看看吧,具体如下:

attachments-2024-04-5IS9vmno6619e83f2409b.png

本文讲述了迭代器与生成器:python中的流式数据处理双雄!具有很好的参考价值,希望对大家有所帮助。一起跟随好学星城小编过来看看吧,具体如下:

Python中的迭代器和生成器是用于处理数据流的重要工具。它们允许你遍历数据集合,而不需要在内存中一次性加载所有数据。这在处理大量数据或无限数据流时特别有用。

迭代器(Iterator)

迭代器是一个可以记住遍历的位置的对象。它从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

创建迭代器

在Python中,你可以通过实现__iter__()和__next__()方法来创建自定义迭代器。__iter__()方法返回迭代器对象本身,__next__()方法返回容器的下一个值。当容器中没有更多元素时,__next__()方法将引发StopIteration异常。

下面是一个简单的迭代器示例:

class MyIterator:

    def __init__(self, start, end):

        self.current = start

        self.end = end


    def __iter__(self):

        return self


    def __next__(self):

        if self.current < self.end:

            value = self.current

            self.current += 1

            return value

        else:

            raise StopIteration


# 使用自定义迭代器

iterator = MyIterator(0, 5)

for i in iterator:

    print(i)

内置迭代器

Python的内置数据类型(如列表、元组、字典和集合)都支持迭代。你可以使用for循环或iter()函数和next()函数来遍历它们。

例如:

my_list = [1, 2, 3, 4, 5]

iterator = iter(my_list)

print(next(iterator))  # 输出 1

print(next(iterator))  # 输出 2

生成器(Generator)

生成器是一种特殊类型的迭代器,它使用了yield关键字而不是return来返回值。生成器允许你按需生成值,而不是一次性计算并存储所有值。这使得生成器在处理大量数据或无限数据流时非常高效。

创建生成器

你可以通过定义一个包含yield语句的函数来创建生成器。当调用这个函数时,它并不立即执行,而是返回一个生成器对象。然后,你可以使用next()函数或for循环来遍历生成器的值。每次调用next()时,生成器会执行到下一个yield语句,并返回相应的值。当生成器函数执行完毕时,它会引发StopIteration异常。

下面是一个简单的生成器示例:

def my_generator(start, end):

    current = start

    while current < end:

        yield current

        current += 1


# 使用生成器

gen = my_generator(0, 5)

for i in gen:

    print(i)

生成器表达式

除了定义包含yield的函数之外,你还可以使用生成器表达式来创建生成器。生成器表达式类似于列表推导式,但它们是按需生成值的,而不是一次性生成所有值。生成器表达式使用圆括号而不是方括号。

例如:

# 列表推导式(一次性生成所有值)

squares = [x ** 2 for x in range(10)]

print(squares)  # 输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


# 生成器表达式(按需生成值)

squares_gen = (x ** 2 for x in range(10))

print(next(squares_gen))  # 输出 0

print(next(squares_gen))  # 输出 1

迭代器的优点

1. 内存效率:迭代器不需要一次性加载所有数据到内存中,而是按需加载。这对于处理大数据集或流式数据非常有用。

2. 顺序访问:迭代器提供了一种顺序访问集合元素的方式,而不需要知道底层数据的具体实现。

3. 可重用性:你可以通过多次调用iter()函数来重新使用迭代器,只要迭代器的状态被重置。

4. 通用性:Python的for循环和许多内置函数(如map(), filter(), reduce()等)都支持迭代器协议,这意味着你可以使用迭代器与这些结构无缝集成。

生成器的优点

生成器除了具有迭代器的所有优点外,还有以下独特的优点:

1. 简洁性:生成器允许你用更少的代码实现相同的功能。与定义类并实现__iter__()和__next__()方法相比,使用yield关键字更加简洁。

2. 状态保持:生成器会自动保存其执行状态,包括局部变量和指令指针。每次调用next()或__next__()时,生成器都会从上次离开的地方继续执行。

3. 懒加载:生成器是惰性计算的,这意味着它们只在需要时才生成值。这可以提高程序的性能,特别是在处理大量数据时。

使用场景示例

迭代器使用场景:

• 遍历文件的每一行,而不需要将整个文件加载到内存中。

• 实现自定义的数据结构,如链表、树等,并提供迭代功能。

• 与数据库交互时,逐行获取查询结果,而不是一次性获取所有结果。

生成器使用场景:

• 创建一个无限的数值序列,如斐波那契数列。

• 实现协程(coroutine),用于编写异步代码。

• 在处理大数据时,按需生成和处理数据块,以减少内存占用。

示例代码

斐波那契数列生成器:

def fibonacci(n):

    a, b = 0, 1

    for _ in range(n):

        yield a

        a, b = b, a + b


# 使用生成器获取斐波那契数列的前10个数

fib_gen = fibonacci(10)

for num in fib_gen:

    print(num)

文件逐行读取迭代器:


class LineIterator:

    def __init__(self, filename):

        self.filename = filename

        self.file = None


    def __iter__(self):

        return self


    def __next__(self):

        if self.file is None:

            self.file = open(self.filename, 'r')

        line = self.file.readline().strip()

        if line:

            return line

        else:

            self.file.close()

            raise StopIteration


# 使用自定义迭代器逐行读取文件

lines = LineIterator('example.txt')

for line in lines:

    print(line)

进阶内容:生成器函数与生成器表达式

生成器函数

之前我们已经介绍了生成器函数,它们使用yield关键字而不是return来产生一系列的值。每次调用生成器函数时,它都会“记住”上次返回的位置,并在下次调用时从那个位置继续执行。这使得生成器函数非常适合表示无限的或者非常大的序列。


示例:无限的偶数生成器


def even_numbers():

    num = 0

    while True:

        yield num

        num += 2


# 创建一个生成器对象

even_gen = even_numbers()


# 打印前5个偶数

for _ in range(5):

    print(next(even_gen))

生成器表达式

生成器表达式是创建生成器的另一种简洁方式。它们看起来很像列表推导式,但是使用圆括号而不是方括号。生成器表达式按需生成值,而不是一次性生成整个列表,从而节省内存。


示例:使用生成器表达式创建平方数生成器


# 列表推导式,一次性生成所有值

squares_list = [x ** 2 for x in range(10)]

print(squares_list)  # 输出 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


# 生成器表达式,按需生成值

squares_gen = (x ** 2 for x in range(10))

for square in squares_gen:

    print(square)  # 逐个输出平方数

协同程序(Coroutines)与yield from

在Python中,生成器还可以作为协同程序(coroutines)使用,这意味着它们可以接收值(通过send()方法)并在生成器之间委派任务(通过yield from语句)。这使得生成器不仅可以产出值,还可以消费值,并与其他生成器协同工作。


示例:使用yield from委派生成器


def countdown(n):

    while n > 0:

        recv = yield n

        if recv is not None:

            print('Countdown interrupted with:', recv)

            n = recv  # Reset countdown value

        else:

            n -= 1


def delegating_generator(n):

    # Yield values from another generator

    yield from countdown(n)

    print("Countdown has finished.")


gen = delegating_generator(5)

print(next(gen))  # 5

print(gen.send(3))  # Interrupts countdown and sets n to 3

print(next(gen))  # 2

print(next(gen))  # 1

try:

    print(next(gen))  # Raises StopIteration, but "Countdown has finished." is printed first

except StopIteration:

    pass

迭代工具与内置函数

Python标准库提供了许多有用的迭代工具和内置函数,可以与迭代器和生成器一起使用,如itertools模块和map(), filter(), reduce()等函数。


示例:使用itertools.count创建一个无限的计数器


import itertools


# 创建一个从10开始的无限计数器

counter = itertools.count(start=10)


# 打印前5个数

for _ in range(5):

    print(next(counter))  # 输出 10, 11, 12, 13, 14

总结

Python的迭代器和生成器是处理流式数据和大型数据集的强大工具。它们允许你以内存高效的方式遍历数据,并提供了一种简洁的语法来定义自定义的迭代逻辑。通过结合使用yield、生成器表达式、协同程序和迭代工具,你可以编写出既高效又富有表现力的代码。

更多相关技术内容咨询欢迎前往并持续关注好学星城论坛了解详情。

想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg

  • 发表于 2024-04-13 10:05
  • 阅读 ( 53 )
  • 分类:Python开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

1478 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1478 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章