Python“列表推导式”和“生成器表达式”的区别

列表推导式

什么是列表推导式

[结果 for 变量 in 可迭代对象 if 条件]

# 获取200以内的偶数:
_list = [i for i in range(0, 201) if i % 2 == 0]
print(_list)

运行结果:
在这里插入图片描述

生成器表达式

什么是生成器

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

所以,如果列表元素可以按照某种算法推算出来,那我们就可以在循环当中不断地推导它,生成元素。这样就不必创建完整的list,从而大大节省了存储空间。

在python中,这种一边循环一边计算的机制,称为生成器:generator.

生成器表达式和列表表达式差不多,只是把[]换为()即可:

gen = ("众将士,随我第%s次冲~~~" % i for i in range(10))
print(next(gen)) #可以通过next(生成器对象)获取生成器的下一个返回值。
print("********************")
for i in gen:
    print(i)
print("********************")
for i in gen:
    print(i)

运行结果:
运行结果

扩展

def add(a, b):
    return a + b
def generate():
    for r_i in range(5):
        yield r_i
        
g = generate()
for n in [1, 5]:
    g = (add(n, i) for i in g)
for item in g:
    print(item)

在这里插入图片描述

def add(a, b):
    return a + b
def generate():
    for r_i in range(5):
        yield r_i

g = generate()
for n in [1, 5]:
    g = (add(n, i) for i in g)
    for item in g:
        print(item)

在这里插入图片描述
生成器保存的是算法!!!!!!!!!每次调用next(g),就计算出g的下一个元素的值,直接计算到最后一个元素,如果没有更多的元素时,抛出StopIteration异常。

在实际编程当中,使用最多的是,将生成器以for方式来使用。通过for迭代,拿到元素,不用担心StopIteration异常

练习

查找列表中重复元素

lstA = [4, 2, 5, 5, 6, 8, 6, 5, 2, 3, 2, 6, 2, 5, 4, 2, 3, 6, 9, 5, 2, 2, 6, 8, 2, 1, 4, 5, 6, 8, 5, 2]
el = lstA
from collections import defaultdict

def listDu(seq):
    '''
    统计列表中重复的元素并显示其所在的所有位置
    :param seq: 需要统计的列表
    :return: 生成器表达式
    '''
    allNum = defaultdict(list) #当字典里的key不存在但被查找时,返回的不是keyError而是一个默认值,这个默认值是参数(工厂函数)的默认值,
    for i, item in enumerate(seq):
        allNum[item].append(i)
    return ((key, l) for key, l in allNum.items() if len(l) > 1)

for elOne in sorted(listDu(el)):
    print(elOne)

运行结果
在这里插入图片描述

总结:两者区别

  • 生成器表达式每次处理一个对象,而不是一口气处理和构造整个数据结构,这样做可以节省大量的内存,在处理的数据量较大时,最好考虑使用生成器表达式而不是列表推导式。
  • 得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器,但是你可以遍历输出。而且列表推导式可以多次迭代,生成器表达式只能单次迭代

注意

生成器具有惰性机制,生成器只有在访问时候才取值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 开胃菜 2. 使用 Python 解释器 2.1. 调用 Python 解释器 2.1.1. 参数传递 2.1.2. 交互模式 2.2. 解释器及其环境 2.2.1. 错误处理 2.2.2. 执行 Python 脚本 2.2.3. 源程序编码 2.2.4. 交互执行文件 2.2.5. 本地化模块 3. Python 简介 3.1. 将 Python 当做计算器 3.1.1. 数字 3.1.2. 字符串 3.1.3. 关于 Unicode 3.1.4. 列表 3.2. 编程的第一步 4. 深入 Python 流程控制 4.1. if 语句 4.2. for 语句 4.3. The range() 函数 4.4. break 和 continue 语句, 以及循环中的 else 子句 4.5. pass 语句 4.6. 定义函数 4.7. 深入 Python 函数定义 4.7.1. 默认参数值 4.7.2. 关键字参数 4.7.3. 可变参数列表 4.7.4. 参数列表的分拆 4.7.5. Lambda 形式 4.7.6. 文档字符串 4.8. 插曲:编码风格 5. 数据结构 5.1. 关于列表更多的内容 5.1.1. 把链表当作堆栈使用 5.1.2. 把链表当作队列使用 5.1.3. 列表推导式 5.1.4. 嵌套的列表推导式 5.2. del 语句 5.3. 元组和序列 5.4. 集合 5.5. 字典 5.6. 循环技巧 5.7. 深入条件控制 5.8. 比较序列和其它类型 6. 模块 6.1. 深入模块 6.1.1. 作为脚本来执行模块 6.1.2. 模块的搜索路径 6.1.3. “编译的” Python 文件 6.2. 标准模块 6.3. dir() 函数 6.4. 包 6.4.1. 从 * 导入包 6.4.2. 包内引用 6.4.3. 多重目录中的包 7. 输入和输出 7.1. 格式化输出 7.1.1. 旧式的字符串格式化 7.2. 文件读写 7.2.1. 文件对象方法 7.2.2. pickle 模块 8. 错误和异常 8.1. 语法错误 8.2. 异常 8.3. 异常处理 8.4. 抛出异常 8.5. 用户自定义异常 8.6. 定义清理行为 8.7. 预定义清理行为 9. 类 9.1. 术语相关 9.2. Python 作用域和命名空间 9.2.1. 作用域和命名空间示例 9.3. 初识类 9.3.1. 类定义语法 9.3.2. 类对象 9.3.3. 实例对象 9.3.4. 方法对象 9.4. 一些说明 9.5. 继承 9.5.1. 多继承 9.6. 私有变量 9.7. 补充 9.8. 异常也是类 9.9. 迭代器 9.10. 生成器 9.11. 生成器表达式 10. Python 标准库概览 10.1. 操作系统接口 10.2. 文件通配符 10.3. 命令行参数 10.4. 错误输出重定向和程序终止 10.5. 字符串正则匹配 10.6. 数学 10.7. 互联网访问 10.8. 日期和时间 10.9. 数据压缩 10.10. 性能度量 10.11. 质量控制 10.12. “瑞士军刀” 11. 标准库浏览 – Part II 11.1. 输出格式 11.2. 模板 11.3. 使用二进制数据记录布局 11.4. 多线程 11.5. 日志 11.6. 弱引用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一念之间hw

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值