Python列表解析式(List Comprehension)

1、列表解析 List Comprehension

举例:生成一个列表,元素0~9,对每一个元素自增1后求平方返回新列表

传统做法

# 传统做法
lst = list(range(10))
newlist = []
for i in range(len(lst)-1):
    newlist.append((i + 1) ** 2)
print(newlist)

执行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81]

使用列表解析式

lst = list(range(10))
print([((i + 1) ** 2) for i in lst])

执行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

语法

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

列表解析式是一种语法糖

  • 编译器会优化,不会因为简写而影响效率,反而因优化提高了效率
  • 减少程序员工作量,减少出错
  • 简化了代码,但可读性增强

举例1:获取10以内的偶数

print([x for x in range(10) if x % 2 == 0])

#执行结果:
[0, 2, 4, 6, 8]

举例2:

newlist = [print(i) for i in range(10)],请问打印出什么? newlist 打印出来是什么?
newlist = [print(i) for i in range(10)]

print(newlist)    #print函数返回值为None

#执行结果:
0
1
2
3
4
5
6
7
8
9
[None, None, None, None, None, None, None, None, None, None]

举例3:获取20以内的偶数,如果同时3的倍数也打印

列表解析式不允许存在else语句

print([i for i in range(20) if i % 2 == 0 or i % 3 == 0])

#执行结果:
[0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18]

2、列表解析进阶

[expr for item in iterable if cond1 if cond2]
[expr for i in iteravle1 for j in iterable2]    #两层循环

举例1:

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

#执行结果:
[(5, 24), (6, 24)]
[(5, 24), (6, 24)]
[(5, 24), (6, 24)]

举例2:返回1-10平方的列表

[(x ** 2) for x in range(1,11)]

举例3:

有一个列表lst= [1,4,9,16,2,5,10,15], 生成一一个新列表,要求新列表元素是Ist相邻2项的和

lst= [1,4,9,16,2,5,10,15]
newlist = [(lst[i] + lst[i+1]) for i in range(len(lst) - 1)]
print(newlist)

3、生成器表达式 Generator expression

语法:

  • (返回值 for 元素 in 可迭代对象 if 条件)
  • 列表解析式的中括号换成小括号就行了
  • 返回一个生成器

和列表解析式的区别:

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

生成器:

  • 可迭代对象
  • 迭代器
g = ("{:04}".format(i) for i in range(1,11))
print(g)
next(g)
for i in g:
    print(i)

#执行结果:
<generator object <genexpr> at 0x000002771C5B3548>
0002
0003
0004
0005
0006
0007
0008
0009
0010

总结:

  • 延迟计算
  • 返回迭代器,可以迭代
  • 从前到后走完一遍,不能回头

而列表:

  • 立即计算
  • 返回的不是迭代器,返回可迭代对象列表
  • 从前到后走完一遍,可以重新回头迭代

思考1:it = (print(“{}”.format(i+1) for i in range(2)))

first = next(it)    #1
second = next(it)   #2
val = first + second

#执行结果:
<generator object <genexpr> at 0x000001B2AE19E548>
Traceback (most recent call last):
......
    first = next(it)
TypeError: 'NoneType' object is not an iterator# 因为 first,second 返回值为None

思考2:

it = (x for x in range(10) if x % 2)    # x % 2 = 1 输出
first = next(it)     # 1
second = next(it)    # 3
val = first + second # 4
print(val)

执行结果:
4

# first,second 的返回值为 1,3

生成器表达式和列表解析式的对比

计算方式

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

内存占用

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

计算速度

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

4、集合解析式

语法:

  • {返回值 for 元素 in 可迭代对象 if 条件}
  • 列表解析式的中括号换成大括号{}就行了
  • 立即返回一个集合

用法:

print({(x, x + 1) for x in range(10)})

执行结果:

{(0, 1), (1, 2), (7, 8), (6, 7), (4, 5), (5, 6), (8, 9), (9, 10), (2, 3), (3, 4)}
#python学习交流群:711312441
print({[x] for x in range(10)})    #新建一个集合,集合的元素要求可哈希,执行错误

5、字典解析式

语法:

  • {返回值 for 元素 in 可迭代对象 if 条件}
  • 列表解析式的中括号换成大括号{}就行了
  • 使用key:value形式
  • 立即返回一个字典

用法:

print({x:(x,x+1) for x in range(10)})

#执行结果:
{0: (0, 1), 1: (1, 2), 2: (2, 3), 3: (3, 4), 4: (4, 5), 5: (5, 6), 6: (6, 7), 7: (7, 8), 8: (8, 9), 9: (9, 10)}
------------------------------------------- 
print({x:[x,x+1] for x in range(10)})

#执行结果:
{0: [0, 1], 1: [1, 2], 2: [2, 3], 3: [3, 4], 4: [4, 5], 5: [5, 6], 6: [6, 7], 7: [7, 8], 8: [8, 9], 9: [9, 10]}
-------------------------------------------

print({(x,):[x,x+1] for x in range(10)})
 
print({[x]:[x,x+1] for x in range(10)})    #key:[x]不可哈希

print({chr(0x41+x):x**2 for x in range(10)})

#执行结果:
{'A': 0, 'B': 1, 'C': 4, 'D': 9, 'E': 16, 'F': 25, 'G': 36, 'H': 49, 'I': 64, 'J': 81}
-------------------------------------------

print({str(x):y for x in range(3) for y in range(4)})    #覆盖

#执行结果:
{'0': 3, '1': 3, '2': 3}

6、总结:

  • Python2弓|入列表解析式
  • Python2.4引入生成器表达式
  • Python3引入集合、字典解析式,并迁移到了2.7
  • 一般来说,应该多应用解析式,简短、高效
  • 如果一个解析式非常复杂,难以读懂,可以考虑拆解成for循环
  • 生成器和迭代器是不同的对象,但都是可迭代对象
  • 可迭代对象范围更大,都可以使用for循环遍历
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值