Python中列表解析式与生成器表达式

列表解析式

语法

  • [返回值 for 元素 in 可迭代对象 if 条件]
  • 使用[ ],内部是for循环,,if条件语句可选
  • 返回一个新的列表

列表解析式是一种语法糖

  • 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
  • 减少程序员工作量,减少出错
  • 简化了代码,但可读性增强
    例: 获取10以为的偶数
# 非列表解析式写法
even =[]
for x in rang(10):
	if x % 2 == 0:
		even.append(x)
------------------------------
# 列表解析式写法  
even = [x for x in range(10) if x%2 == 0]

以下例子返回值会是什么?

newlist = [print(i) for i in range(10)]
print(newlist)
newlist1 = [str(i) for i in range(10)]
print(newlist1)

输出结果:

0
1
2
3
4
5
6
7
8
9
[None, None, None, None, None, None, None, None, None, None]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  • 解析:newlist最后列表中会出现10个None,是因为必须要把函数执行完了用print(i)的返回值来填充列表,而print(i)的返回值是None。newlist1中str(i)的返回值是字符串

列表解析进阶

  • [expr for item in iterable if cond1 if cond2],不允许出现else
    等价于
    ret = [ ]
    for iterm in iterable:
        if cond1:
            if cond2:
                ret.append(expr)
  • 例: 20以内,既能被2整除又能被3整除的数
print([i for i in range(20) if i%2 == 0 and i%3 == 0])
print([i for i in range(20) if i%2 == 0 if i%3 == 0])

输出结果

[0, 6, 12, 18]
[0, 6, 12, 18]
  • [expr for i in iterable1 for j in iterable2 ]
    等价于
    ret = []
    for i in iterable1:
        for j in iterable2:
            ret.append(expr)
  • 例:
print([(x,y) for x in 'abc' for y in range(3)])
print([[x,y] for x in 'abc' for y in range(3)])
print([{x,y} for x in 'abc' for y in range(3)])

输出结果:

[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2), ('c', 0), ('c', 1), ('c', 2)]

[['a', 0], ['a', 1], ['a', 2], ['b', 0], ['b', 1], ['b', 2], ['c', 0], ['c', 1], ['c', 2]]

[{0, 'a'}, {1, 'a'}, {2, 'a'}, {0, 'b'}, {1, 'b'}, {2, 'b'}, {0, 'c'}, {1, 'c'}, {2, 'c'}]

请问下面3中输出各是什么?

print([(x,y) for x in range(7) if x >4 for y in range(20,25) if y>23])
print([(x,y) for x in range(7) for y in range(20,25)if x>4 if y>23])
print([(x,y) for x in range(7) for y in range(20,25)if x>4 and y>23])

输出结果

[(5, 24), (6, 24)]
[(5, 24), (6, 24)]
[(5, 24), (6, 24)]

生成器表达式

语法

  • (返回值 for 元素 in 可迭代对象 if 条件)
  • 将列表解析式的 [] 换成 () 即可。
  • 使用(),内部是for循环,,if条件语句可选
  • 返回一个生成器

和列表解析式的区别

  • 生成器表达式是按需要计算(或称惰性求值 、延迟计算),需要的时候才计算值
  • 列表解析式是立即返回值

生成器

  • 可迭代对象
  • 迭代器
  • 例1使用生成器表达式:
g =("{:04}".format(i) for i in range(1,5))
next(g)
for x in g:
    print(x)
print('-----------')
for x in g:
    print(x)

输出结果

0002
0003
0004
-----------

解析:1.延迟计算;2.返回迭代器,可以迭代;3.从前到后走完一遍后,不能回头

  • 例2:将例1改成列表解析式:
g =["{:04}".format(i) for i in range(1,5)]
for x in g:
    print(x)
print('-----------')
for x in g:
    print(x)
  • 输出结果
0001
0002
0003
0004
-----------
0001
0002
0003
0004
  • 解析:1.立即计算;2.返回的不是迭代,返回可迭代对象列表;3.从前到后走完一遍,可以重新回头迭代

生成器和列表解析式对比

计算方法

  • 生成器表达式延时计算,列表解析式立即计算

内存占用

  • 单从返回值本身来说,生成器表达式省内存,列表解析式返回新的列表
  • 生成器没有数据,内存占用极少,它是使用时一个个返回数据。如果将这些返回的数据合起来占用的内存和列表解析式差不多。但是它不需要立即占用这么多内存
  • 列表解析式构造性的列表需要立即占用内存,不管你是否需要立即使用这么多数据

计算速度

  • 单从计算时间看,生成器表达式耗时非常短,列表解析式耗时长
  • 但是生成器本身并没有返回任何值,只返回了一个生成器对象
  • 列表解析式构造并返回了一个新的列表,所以看起来耗时了

集合解析式

语法

  • {返回值for 元素 in可迭代对象 if 条件}
  • 列表解析式的[]换成{}即可
  • 立即返回一个集合

用法

{(x, x+1) for x in range(10)}
注: {[x] for x in range(10)},会报TypeError错误,因为[x]是list,集合内的元素需要可hash,而list是不可hash

字典解析式

语法

  • {返回值for 元素 in可迭代对象 if 条件}
  • 列表解析式的[]换成{}即可
  • 使用key.value形式
  • key值需要可hash
  • 立即返回一个字典

用法

{x:(x,x+1) for x in range(5)}
{x:[x,x+1] for x in range(5)}
{(x,):[x,x+1] for x in range(5)}
注:{[x]:[x,x+1] for x in range(5)},会报TypeError错误,因为key是list,不可hash
{str(x):y for x in range(3) for y in range(4)} 会输出几个元素呢?
输出结果: {‘0’:3, ‘1’:3, ‘2’:3} 原因是字典有去重特性,而后一次的输出结果会覆盖前一次。

总结

  • Python2 引入列表解析式
  • Python2.4 引入生成器表达式
  • Python3 引入集合、字典解析式,并迁徙到了2.7
  • 一般来说,应该多应用解析式,简短、高效
  • 如果一个解析式非常复杂,难以读懂,可以考虑拆解成for 循环
  • 生成器和迭代是不同的对象,但都是可迭代对象
  • 可迭代对象范围更大,都可以使用for循环遍历
    在这里插入图片描述

习题:

第一题 使用列表解析式 打印九九乘法表 第一题
第二题 使用列表解析式生成 “0001.abadicddws” 格式的ID号 第一题
要求ID格式是以点号分割,左边是4位从1开始的整数,右边是10位随机小写英文字母。
请依次生成前100个ID的列表,如图:

'0001.bbcomlkdyt'
'0002.yzjudytpna'
'0003.zycscjsvfy'
'0004.hhvqzlukui'
'0005.xissuxwsou'

习题参考答案

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值