翼度科技»论坛 编程开发 python 查看内容

python3 生成器表达式

8

主题

8

帖子

21

积分

新手上路

Rank: 1

积分
21
在 Python3 中,生成器表达式是一种语言结构,它可以快速地创建一个可迭代对象。生成器表达式类似于列表推导式,但使用圆括号而不是方括号,并且返回的是一个生成器对象而不是一个列表。
在 Python3 中,生成器表达式有两种类型:生成器函数和生成器表达式。

  • 生成器函数:
生成器函数是一种特殊的函数,在函数中使用 yield 语句来生成一个值,然后暂停函数执行并保留当前状态,等待下一次调用时继续执行。生成器函数的优点是可以处理大量数据,因为它们只需要在内存中保存一个值,而不是全部保存在内存中。
例如,以下是一个生成器函数,它可以生成斐波那契数列中的前 n 个数字:
  1. def fibonacci(n):
  2.     a, b = 0, 1
  3.     for i in range(n):
  4.         yield a
  5.         a, b = b, a + b
复制代码

  • 生成器表达式:
生成器表达式是使用圆括号包围的表达式,其中包含一个 for 循环和一个可选的 if 条件。生成器表达式可以用来生成一个序列,这个序列可以通过迭代访问,但不必事先将所有元素保存在内存中。
例如,以下生成器表达式可以生成一个包含从 1 到 10 的偶数的生成器对象:
  1. gen = (i for i in range(1, 11) if i % 2 == 0)
复制代码
注意事项:
<ol>生成器表达式可以节省内存空间,但是如果需要多次使用生成器对象中的值,则需要将其转换为列表或其他数据结构。
如果生成器表达式中的代码太长或复杂,则建议使用生成器函数来代替,以提高代码的可读性和可维护性。
如果生成器表达式中的代码有副作用(例如修改了全局变量),则可能会导致意外行为,应该避免这种情况。
生成器表达式可以嵌套,但是应该注意不要嵌套过深导致代码难以理解。例如:
  1. gen = ((i, j) for i in range(1, 4) for j in range(4, 7))
复制代码
这个生成器表达式可以生成一个包含所有 (1,4) 到 (3,6) 的元组的生成器对象。
生成器表达式中的 for 循环可以有多个,每个循环可以使用一个 if 条件。例如:
  1. gen = (i * j for i in range(1, 4) if i % 2 == 0 for j in range(4, 7) if j % 2 != 0)
复制代码
这个生成器表达式可以生成一个包含所有偶数 i 与奇数 j 的乘积的生成器对象。
生成器表达式中的变量作用域只在生成器表达式内部,不会泄露到外部。例如:
  1. x = 10
  2. gen = (x for x in range(1, 5))
  3. print(list(gen))    # 输出 [1, 2, 3, 4]
  4. print(x)    # 输出 10,说明 x 只在生成器表达式内部存在,不会影响外部变量 x 的值。
复制代码
生成器表达式可以和其他 Python 的内置函数或模块一起使用,例如 map、filter、itertools 等。例如:
  1. import itertools
  2. # 使用 map 函数和生成器表达式生成一个列表,其中每个元素都是平方数。
  3. lst = list(map(lambda x: x ** 2, (i for i in range(1, 5))))
  4. print(lst)    # 输出 [1, 4, 9, 16]
  5. # 使用 itertools 模块中的 zip_longest 函数和生成器表达式生成一个包含所有输入迭代器的元组的列表。
  6. lst = list(itertools.zip_longest((i for i in range(1, 5)), ('a', 'b', 'c')))
  7. print(lst)    # 输出 [(1, 'a'), (2, 'b'), (3, 'c'), (4, None)]
复制代码
在使用生成器表达式时,应该尽可能地使用惰性求值,即只生成需要的元素,并且在使用完之后立即释放相应的资源。这样可以避免不必要的内存占用和性能问题。
处理大型数据集,例如从文件或数据库中读取数据,并将其用作生成器表达式的输入。这样可以避免一次性加载所有数据,并且节省内存空间。
  1. with open('data.txt') as f:
  2.     gen = (line.strip() for line in f if 'error' in line)
  3.     for item in gen:
  4.         print(item)
复制代码
通过生成器表达式实现惰性求值,例如只有当需要时才计算函数的值。这样可以避免不必要的计算和内存占用。
  1. def expensive_function(n):
  2.     print(f"Calculating {n}...")
  3.     return n ** 2
  4. gen = (expensive_function(i) for i in range(5))
  5. print(list(gen))    # 输出 Calculating 0... Calculating 1... Calculating 2... Calculating 3... Calculating 4... [0, 1, 4, 9, 16]
复制代码
这个例子中,我们定义了一个函数 expensive_function,并使用一个生成器表达式来生成一个包含前五个数字的平方的列表。在评估生成器表达式时,expensive_function 只有在需要计算平方时才被调用,这样可以避免不必要的计算和内存占用。
在多个迭代器之间生成元素,例如合并两个排序列表并返回一个新的排序列表。[code]def merge_sorted(lst1, lst2):    i, j = 0, 0    while i < len(lst1) and j < len(lst2):        if lst1

举报 回复 使用道具