python3 生成器与生成器表达式

这篇具有很好参考价值的文章主要介绍了python3 生成器与生成器表达式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

在 Python3 中,生成器表达式有两种类型:生成器函数和生成器表达式。

  1. 生成器函数:

生成器函数是一种特殊的函数,在函数中使用 yield 语句来生成一个值,然后暂停函数执行并保留当前状态,等待下一次调用时继续执行。生成器函数的优点是可以处理大量数据,因为它们只需要在内存中保存一个值,而不是全部保存在内存中。

例如,以下是一个生成器函数,它可以生成斐波那契数列中的前 n 个数字:

def fibonacci(n):
    a, b = 0, 1
    for i in range(n):
        yield a
        a, b = b, a + b
xx=fibonacci(9)
print(xx)
  1. 生成器表达式:

生成器表达式是使用圆括号包围的表达式,其中包含一个 for 循环和一个可选的 if 条件。生成器表达式可以用来生成一个序列,这个序列可以通过迭代访问,但不必事先将所有元素保存在内存中。

例如,以下生成器表达式可以生成一个包含从 1 到 10 的偶数的生成器对象:

gen = (i for i in range(1, 11) if i % 2 == 0)

注意事项:

  1. 生成器表达式可以节省内存空间,但是如果需要多次使用生成器对象中的值,则需要将其转换为列表或其他数据结构。
  2. 如果生成器表达式中的代码太长或复杂,则建议使用生成器函数来代替,以提高代码的可读性和可维护性。
  3. 如果生成器表达式中的代码有副作用(例如修改了全局变量),则可能会导致意外行为,应该避免这种情况。
  4. 生成器表达式可以嵌套,但是应该注意不要嵌套过深导致代码难以理解。例如:
    gen = ((i, j) for i in range(1, 4) for j in range(4, 7))

    这个生成器表达式可以生成一个包含所有 (1,4) 到 (3,6) 的元组的生成器对象。

  5. 生成器表达式中的 for 循环可以有多个,每个循环可以使用一个 if 条件。例如:
    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 的乘积的生成器对象。

  6. 生成器表达式中的变量作用域只在生成器表达式内部,不会泄露到外部。例如:
    x = 10
    gen = (x for x in range(1, 5))
    print(list(gen))    # 输出 [1, 2, 3, 4]
    print(x)    # 输出 10,说明 x 只在生成器表达式内部存在,不会影响外部变量 x 的值。
  7. 生成器表达式可以和其他 Python 的内置函数或模块一起使用,例如 map、filter、itertools 等。例如:
    import itertools
    
    # 使用 map 函数和生成器表达式生成一个列表,其中每个元素都是平方数。
    lst = list(map(lambda x: x ** 2, (i for i in range(1, 5))))
    print(lst)    # 输出 [1, 4, 9, 16]
    
    # 使用 itertools 模块中的 zip_longest 函数和生成器表达式生成一个包含所有输入迭代器的元组的列表。
    lst = list(itertools.zip_longest((i for i in range(1, 5)), ('a', 'b', 'c')))
    print(lst)    # 输出 [(1, 'a'), (2, 'b'), (3, 'c'), (4, None)]
  8. 在使用生成器表达式时,应该尽可能地使用惰性求值,即只生成需要的元素,并且在使用完之后立即释放相应的资源。这样可以避免不必要的内存占用和性能问题。
  9. 处理大型数据集,例如从文件或数据库中读取数据,并将其用作生成器表达式的输入。这样可以避免一次性加载所有数据,并且节省内存空间。
    with open('data.txt') as f:
        gen = (line.strip() for line in f if 'error' in line)
        for item in gen:
            print(item)
  10. 通过生成器表达式实现惰性求值,例如只有当需要时才计算函数的值。这样可以避免不必要的计算和内存占用。
    def expensive_function(n):
        print(f"Calculating {n}...")
        return n ** 2
    
    gen = (expensive_function(i) for i in range(5))
    print(list(gen))    # 输出 Calculating 0... Calculating 1... Calculating 2... Calculating 3... Calculating 4... [0, 1, 4, 9, 16]

    这个例子中,我们定义了一个函数 expensive_function,并使用一个生成器表达式来生成一个包含前五个数字的平方的列表。在评估生成器表达式时,expensive_function 只有在需要计算平方时才被调用,这样可以避免不必要的计算和内存占用。

  11. 在多个迭代器之间生成元素,例如合并两个排序列表并返回一个新的排序列表。
    def merge_sorted(lst1, lst2):
        i, j = 0, 0
        while i < len(lst1) and j < len(lst2):
            if lst1[i] <= lst2[j]:
                yield lst1[i]
                i += 1
            else:
                yield lst2[j]
                j += 1
        yield from lst1[i:]
        yield from lst2[j:]
    
    lst1 = [1, 3, 5, 7]
    lst2 = [2, 4, 6, 8]
    gen = merge_sorted(lst1, lst2)
    print(list(gen))    # 输出 [1, 2, 3, 4, 5, 6, 7, 8]

    这个例子中,我们定义了一个 merge_sorted 函数来合并两个排序列表,并返回一个新的排序列表。在函数中,我们使用一个生成器函数来生成所有排好序的元素,并在函数返回之前返回它们。这个方法可以在处理大型数据集时节省内存空间,并且可以避免不必要的排序或其他操作。

  12. 用于过滤和转换数据,例如将一个列表中的所有元素转换为字符串并删除其中的空格。
    lst = [' hello ', ' world', '', 'python', '']
    gen = (s.strip() for s in lst if s)
    print(list(gen))    # 输出 ['hello', 'world', 'python']

    这个例子中,我们使用一个生成器表达式来对列表中的所有元素进行过滤和转换。具体来说,我们首先使用 if 子句来过滤出所有不为空的字符串,然后使用 strip 方法来删除每个字符串的前导和尾随空格。最后,我们将经过处理的字符串返回为一个生成器对象,并将其转换为一个列表。

  13. 生成器表达式可以与其他 Python 内置函数(如 map 和 filter)和模块(如 itertools)结合使用,以实现更高效和优雅的代码。

  14. 在使用生成器表达式时,应该尽可能地使用惰性求值,即只生成需要的元素,并在使用完之后立即释放相应的资源。这样可以避免不必要的内存占用和性能问题。

  15. 如果生成器表达式中的代码有副作用(例如修改了全局变量),则可能会导致意外行为,应该避免这种情况。

  16. 在编写长的生成器表达式时,建议将其分解成多个简单的表达式或生成器函数,以提高代码的可读性和可维护性。

  17. 在使用生成器表达式时,应该学会使用列表推导式和普通的 for 循环来进行比较,以选择最适合特定任务的工具。

  18. 最后,需要注意的是,生成器表达式虽然非常强大和方便,但也并非万能的。在某些情况下,还是需要使用其他语言结构或算法来解决问题。

  19. 在使用生成器表达式时,应该避免使用过多的嵌套循环和条件语句,以免代码变得难以阅读和维护。在这种情况下,建议考虑使用其他数据结构或算法。

  20. 使用生成器表达式时,应该尽可能地保持代码简单和易读。这包括命名变量、注释代码和格式化输出,以便其他人可以理解你的代码。

  21. 在使用生成器表达式时,需要注意一些性能问题。例如,在处理大型数据集时,可能需要考虑使用并行计算或其他优化算法来提高效率。让我们来看一个例子,说明生成器表达式和列表推导式之间的差异:

让我们来看一个例子,说明生成器表达式和列表推导式之间的差异:

# 列表推导式
lst = [i ** 2 for i in range(1, 11)]
print(lst)

# 生成器表达式
gen = (i ** 2 for i in range(1, 11))
print(list(gen))

个例子中,我们首先使用列表推导式创建一个包含前 10 个数字的平方的列表。然后,我们使用一个生成器表达式来创建一个包含相同元素的生成器对象,并将其转换为一个列表。

一般来说,列表推导式比起生成器表达式更加适合小型数据集,因为它们可以在内存中完全构建出一个列表,并且可以在需要时随时进行索引和修改。另一方面,生成器表达式更适合大型数据集,因为它们只返回必要的元素,而且可以逐个处理每个元素,从而节省内存空间。

Python标准库还提供了许多内置函数和模块,可以帮助我们更加方便地处理和操作生成器。

其中一个比较常见的内置函数是next()函数。它用于从生成器中获取下一个值,并将生成器的执行状态从上一次挂起的位置继续向下执行。

以下是一个使用next()函数打印斐波那契数列的示例:

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

# 输出前10项斐波那契数列
fib = fibonacci()
for i in range(10):
    print(next(fib))

在这个示例中,使用一个无限循环的生成器函数来计算斐波那契数列。然后,通过调用next()函数逐一输出数列的前10项。每次调用next()函数时,生成器函数会从上一次yield语句挂起的位置继续执行,直到下一个yield语句为止。

除了next()函数之外,Python标准库还提供了一些其他有用的生成器相关函数和模块,例如:

  • itertools: 一个集合了许多有用的迭代器函数的模块,如排列、组合、笛卡尔积等。
  • enumerate(): 返回一个由索引和元素组成的迭代器对象,常用于遍历序列时获取元素的索引。
  • filter(): 返回一个由满足某个条件的元素组成的迭代器对象,常用于过滤序列中的元素。
  • map(): 对序列中的每个元素应用一个函数,并返回一个由处理结果组成的迭代器对象。
  • zip(): 将多个序列打包为一个元组构成的迭代器对象,常用于将多个列表或元组同时遍历。

这些函数和模块可以帮助我们更加方便地使用生成器,并让我们的代码变得更加简洁和高效。

 文章来源地址https://www.toymoban.com/news/detail-433324.html

到了这里,关于python3 生成器与生成器表达式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Python】Python系列教程-- Python3 迭代器与生成器(二十)

    往期回顾: Python系列教程–Python3介绍(一) Python系列教程–Python3 环境搭建(二) Python系列教程–Python3 VScode(三) Python系列教程–Python3 基础语法(四) Python系列教程–Python3 基本数据类型(五) Python系列教程-- Python3 数据类型转换(六) Python系列教程-- Python3 推导式(

    2024年02月08日
    浏览(67)
  • Python3 高级教程 | Python3 正则表达式(一)

    目录 一、Python3 正则表达式 (一)re.match函数 (二)re.search方法 (三)re.match与re.search的区别 二、检索和替换 (一)repl 参数是一个函数  (二)compile 函数  (三)findall (四)re.finditer (五)re.split 三、正则表达式对象 re.RegexObject re.MatchObject  四、正则表达式修饰符 - 可

    2024年02月13日
    浏览(60)
  • 力扣:150. 逆波兰表达式求值(Python3)

    给你一个字符串数组  tokens  ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意: 有效的算符为  \\\'+\\\' 、 \\\'-\\\' 、 \\\'*\\\'  和  \\\'/\\\'  。 每个操作数(运算对象)都可以是一个整数或者另一个表达式。 两个整数之间的除法总

    2024年02月05日
    浏览(56)
  • python3字符串格式化用format()好还是 % 表达式好

    左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。 公众号:一点sir,关注领取python编程资料 在 Python 中,使用 format() 方法是更推荐的方式来进行字符串格式化,特别是在Python3中。虽然 % 表达式仍然可以在Python中使用,但已经不推荐使用了,新的项目

    2024年04月16日
    浏览(82)
  • ES6生成器,看似同步的异步流程控制表达风格

    本文分享自华为云社区《3月阅读周·你不知道的JavaScript | ES6生成器,看似同步的异步流程控制表达风格》,作者: 叶一一。 JavaScript开发者在代码中几乎普遍依赖的一个假定:一个函数一旦开始执行,就会运行到结束,期间不会有其他代码能够打断它并插入其间。 ES6引入了

    2024年04月10日
    浏览(57)
  • Python 生成器推导

    生成器理解是在 python 中创建生成器的一种聪明而有效的方法。 它是定义生成器的单行规范,对于理解该语法以高效编码至关重要。 在本文中,我们将学习 python 的生成器和生成器理解以及示例。 Python 中的生成器是返回可迭代或遍历对象的函数,用于创建一次遍历项目的迭

    2024年02月09日
    浏览(64)
  • Python 实现卡密生成(卡密生成器)

    最近我在做一个基于 openCv2 的脚本,顺手写了一个卡密生成器,也给自己保存一下代码。 代码部分 接下来是下载连接,因为比较小就用某云盘了,知道的它下载一直很慢,其实也不算小Python打包出来的东西还是挺大的,压缩包里有一个ui文件不要删,那个是动态加载进的Qt文

    2024年02月21日
    浏览(59)
  • python中的生成器(generator)

    一、生成器 生成器是 Python 中非常有用的一种数据类型,它可以让你在 Python 中更加高效地处理大量数据。生成器可以让你一次生成一个值,而不是一次生成一个序列,这样可以节省内存并提高性能 二、实现generator的两种方式 python中的generator保存的是算法,真正需要计算出值

    2024年02月15日
    浏览(67)
  • python生成器generator的用法

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以

    2024年02月04日
    浏览(62)
  • java时间解析生成定时Cron表达式工具类

    构建Cron表达式 生成计划的详细描述 构建Cron表达式 枚举类 测试

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包