列表解析式(List Comprehension)
语法:
[返回值 for 元素 in 可迭代对象 if 条件]
使用中括号[],内部是for循环,if条件可选.
返回一个新的列表.
列表解析式的作用:
编译器会优化,不会因为简写而影响效率,反而因优化提高了效率.
减少程序员工作量,减少出错.
简化代码,增强可读性.
注意:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
In [26]: newlist = [print(i) for i in range(10)] 0 1 2 3 4 5 6 7 8 9
In [27]: newlist Out[27]: [None, None, None, None, None, None, None, None, None, None]
In [28]: newlist = [i for i in range(10)]
In [29]: newlist Out[29]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-----------------------------------------------------------------------------------------------------------------------
In [30]: [i for i in range(20) if i%2 == 0 elif i%3 == 0] # 列表解析式里面不包括else, elif. File "<ipython-input-30-9cc81af30c39>", line 1 [i for i in range(20) if i%2 == 0 elif i%3 == 0] ^ SyntaxError: invalid syntax
In [31]: [i for i in range(20) if i%2 == 0 and i%3 == 0] Out[31]: [0, 6, 12, 18]
In [32]: |
举例: 生成一个列表,元素0~9,对每一个元素自增1后求平方并返回新列表.
1 2 3 4 5 6 7 8 |
In [23]: for i in range(10): ...: lst.append((i+1)**2) ...:
In [24]: lst Out[24]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [25]: |
使用列表解析式:
1 2 3 4
|
In [25]: [(i+1)**2 for i in range(10)] Out[25]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [26]: |
列表解析式进阶
[返回值 for 元素 in 可迭代对象 if 条件1 if 条件2]
[返回值 for 元素 in 可迭代对象 for 元素1 in 可迭代对象1]
生成器表达式(Generator expression)
语法: (返回值 for 元素 in 可迭代对象 if 条件).
使用小括号().
返回一个生成器.
和列表解析/推导式的区别:
生成器表达式是按需计算(或称惰性求值,延迟计算),需要的时候才计算值.
列表解析式是立即返回值.
生成器:
可迭代对象
迭代器
生成器表达式和列表解析式比较:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
In [32]: g = ("{:04}".format(i) for i in range(1, 5))
In [33]: g Out[33]: <generator object <genexpr> at 0x000001D487ECA570>
In [34]: next(g) Out[34]: '0001'
In [35]: for x in g: ...: print(x) ...: 0002 0003 0004
In [36]: for x in g: ...: print(x) ...:
In [37]:
总结: 延迟计算. 返回迭代器,可以迭代. 从前到后走完一遍后,不能回头. |
In [39]: g = ["{:04}".format(i) for i in range(1, 5)]
In [40]: g Out[40]: ['0001', '0002', '0003', '0004',]
In [41]: for x in g: ...: print(x) ...: 0001 0002 0003 0004
In [42]: ...
总结: 立即计算. 返回的不是迭代器,返回可迭代对象列表. 从前到后走完一遍后,可以重新回头迭代.
|
总结:
生成器表达式 vs 列表解析式:
计算方式:
生成器表达式延迟计算,列表解析式立即计算.
内存占用:
从返回值本身:生成器表达式省内存,列表解析式返回新的列表.
生成器没有数据,内存占用极少,但是使用时,虽然一个个返回返回数据,但是合起来占用内存和列表解析式也差不多.
列表解析式构造新的列表需要占用内存.
计算速度:
但看计算时间,生成器表达式耗时非常短,列表解析式耗时长.
生成器本身并没返回任何值,只返回了一个生成器对象.
列表解析式构造并返回了一个新的列表.
集合解析式
语法: {返回值 for 元素 in 可迭代对象 if 条件}
使用大括号{}.
立即返回一个集合.
用法:
{(x,x+1) for x in range(10)}
{[x] for x in range(10)}
字典解析式
语法: {返回值 for 元素 in 可迭代对象 if 条件}
使用大括号{}.
使用key:value形式.
立即返回一个字典.
用法:
{x:(x,x+1) for x in range(10)}
{x:[x,x+1] for x in range(10)}
{(x,):[x,x+1] for x in range(10)}
{[x]:[x,x+1] for x in range(10)}
{chr(0x41+x):x**2 for x inrange(10)}
注:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
In [45]: {str(x):y for x in range(3) for y in range(4)} Out[45]: {'0': 3, '1': 3, '2': 3}
# 等价于:
dic = {} for x in range(3): for y in range(4): dic[str(x)] = y print(dic) |
总结:
python2引入列表解析式.
python2.4引入生成器表达式.
python3引入集合,字典解析式,并迁移到2.7
一般来说,应多用解析式,简短高效.
如果一个解析式非常复杂,难读懂,要考虑拆解for循环.
生成器和迭代器都是不同的对象,但都是可迭代对象.