Python 生成器:像做菜一样生成数据


Python 生成器:像做菜一样生成数据

想象一下,你正在准备一顿大餐,你需要做很多道菜。你可以一次性把所有菜都做好,但这样会占用很多时间和空间。或者,你可以使用生成器,就像一个聪明的厨师一样,每道菜都按需制作,这样可以节省时间和空间。

生成器就像一个聪明的厨师

  • 你可以定义一个生成器函数,就像告诉厨师每道菜的制作方法。

  • 生成器函数使用 yield 关键字来 “上菜”,每次调用 next() 函数时,它就会 “端出一道菜”。

  • 生成器会记住它上次做菜做到哪里了,下次会从那里继续做菜。

例子:制作水果沙拉

def fruit_salad():
    yield "苹果"  # 端出第一道 "菜":苹果
    yield "香蕉"  # 端出第二道 "菜":香蕉
    yield "橘子"  # 端出第三道 "菜":橘子

salad = fruit_salad()  # 创建一个 "厨师" (生成器)

现在,你可以像品尝每道菜一样,逐个获取水果:

print(next(salad))  # 品尝第一道 "菜":输出 "苹果"
print(next(salad))  # 品尝第二道 "菜":输出 "香蕉"
print(next(salad))  # 品尝第三道 "菜":输出 "橘子"

生成器的优点

  • 节省空间: 你不需要一次性将所有 “菜” 做好,只需要 “按需制作”,节省内存空间。

  • 灵活方便: 你可以根据需要 “点菜”,随时获取下一道 “菜”。

  • 菜谱多样: 你可以使用不同的方式来定义生成器函数,创建各种各样的 “菜肴”。

生成器(Generator)是 Python 中一种特殊的迭代器,它可以用来创建自定义的迭代模式,而无需一次性将所有元素加载到内存中。生成器函数使用 yield 关键字来生成值,而不是 return 关键字。

创建生成器

使用生成器函数:

def my_generator(n):
    for i in range(n):
        yield i

gen = my_generator(3)  # 创建一个生成器对象

使用生成器表达式:

gen = (x**2 for x in range(5))  # 创建一个生成器表达式

使用生成器

# 使用 for 循环
for i in gen:
    print(i)

# 使用 next() 函数
print(next(gen))
print(next(gen))

斐波那契数列生成器

斐波那契数列是一个经典的数学序列,其中每个数字都是前两个数字之和。例如:0, 1, 1, 2, 3, 5, 8, 13, …

使用生成器,我们可以轻松地生成斐波那契数列,而无需一次性计算所有数字。

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

# 生成前 10 个斐波那契数
fib_generator = fibonacci(10)

for number in fib_generator:
    print(number)

代码解释:

yield关键字在Python中用于定义一个生成器函数。当你调用这个函数时,它不会立即执行,而是返回一个生成器对象。当你从这个生成器对象中请求值时(例如通过next()函数或在for循环中),函数会执行,直到遇到yield语句,然后返回yield后面的值。

在本例中,yield a会将当前的a值返回给fib_generator。然后,函数会“暂停”,等待下一次请求值。当下一次请求值时,函数会从暂停的地方继续执行,计算下一个斐波那契数,然后再次遇到yield语句,返回新的a值。

生成器的特性

  • 惰性求值: 生成器只在需要时才生成值,节省内存空间。

  • 状态保持: 生成器函数在每次调用 next() 时会从上次停止的地方继续执行。

  • 单向迭代: 生成器只能向前迭代,不能回退。

  • 可组合性: 生成器可以与其他生成器或迭代器组合使用,创建复杂的迭代模式。

生成器的应用场景

  • 遍历大型数据集

  • 处理数据流

  • 实现自定义迭代模式

  • 编写高效的算法

自动化测试中迭代器的应用案例

迭代器在软件测试中发挥着重要作用,特别是在处理数据驱动测试和需要灵活遍历数据结构的场景中。例如:

数据驱动测试 (Data-Driven Testing)

  • 场景: 测试用例需要使用不同的输入数据进行重复测试,例如测试一个登录功能,需要使用不同的用户名和密码组合。

  • 应用:

    • 使用迭代器从数据源(如 CSV 文件、Excel 表格、数据库)中读取测试数据。
    • 每次迭代生成一组测试数据,用于执行测试用例。
    • 结合测试框架,可以方便地实现参数化测试,提高测试效率。
  • 示例:

def read_test_data(filename):
    with open(filename, 'r') as f:
        for line in f:
            username, password = line.strip().split(',')
            yield username, password

# 使用迭代器读取测试数据
test_data = read_test_data('test_data.csv')

# 遍历测试数据并执行测试用例
for username, password in test_data:
    test_login(username, password)

生成器与迭代器的区别

虽然生成器是一种特殊的迭代器,但它们之间还是存在一些关键区别:

创建方式:

  • 迭代器: 通过调用 iter() 函数作用于可迭代对象(如列表、元组、字符串)来创建。

  • 生成器: 通过定义一个带有 yield 语句的函数来创建。

代码复杂度:

  • 迭代器: 实现迭代器协议需要定义 iter() 和 next() 方法,代码相对复杂。

  • 生成器: 只需要使用 yield 语句,代码更加简洁易懂。

适用场景:

  • 迭代器: 适用于需要多次遍历相同数据集的场景,或者需要随机访问元素的场景。

  • 生成器: 适用于处理大型数据集或无限数据流的场景,或者需要自定义迭代逻辑的场景。

总结:

特性迭代器生成器
创建方式iter(iterable)yield 语句
元素生成方式一次性生成惰性求值
状态保持
代码复杂度较高较低
适用场景多次遍历、随机访问大型数据集、数据流

每篇文章都这么用心,你确定不关注一下我吗 (¬‿¬)

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值