列表解析式和生成器
列表解析式
列表解析式因编译器进行优化,提高了效率,减少出错,增加可读性
语法
- [返回值 for 元素 in 可迭代对象 if条件]
- 使用中括号[],内部是for循环,if条件语句可选
- 返回一个新列表
示例1:
生成一个列表,元素0-9,对每一个元素自增1后求平方返回新列表
#通常写法为: new = [] for i in range(10): new.append((i+1)**2) print(new) #使用列表解析式方法: new = [(i+1)**2 for i in range(10)] print(new)
输出结果相同:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
示例2:
获取10以内的偶数
list = [i for i in range(10) if i % 2 == 0]
输出结果为:
[0, 2, 4, 6, 8]
示例3:
20以内,即能被2整除又能被3整除的数
#以下两种方法都可以
list1 = [i for i in range(20) if i % 2 == 0 if i % 3 == 0] #方法一 list2 = [i for i in range(20) if i % 2 == 0 and i % 3 == 0] #方法二
列表解析式进阶
- [返回值 for i in 可迭代对象A for j in 可迭代对象B]
- 等价于:
list = []
for i in iterableA:
for j in iterableB:
list.append(expr)
示例1:
list1 = [(x,y) for x in "abc" for y in range(3)] list2 = [[x,y] for x in "abc" for y in range(3)] list3 = [{x:y} for x in "abc" for y in range(3)] print(list1) print(list2) print(list3)
输出为:
[('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]] [{'a': 0}, {'a': 1}, {'a': 2}, {'b': 0}, {'b': 1}, {'b': 2}, {'c': 0}, {'c': 1}, {'c': 2}]
示例2:
#以下三种输出一样,但推荐使用第一种方法,效率更高 list1 = [(i,j) for i in range(7) if i>4 for j in range(20,25) if j >23] list2 = [(i,j) for i in range(7) for j in range(20,25) if i>4 if j >23] list3 = [(i,j) for i in range(7) for j in range(20,25) if i>4 and j >23] print(list1) print(list2) print(list3)
输出结果为:
[(5, 24), (6, 24)] [(5, 24), (6, 24)] [(5, 24), (6, 24)]
复杂示例
返回1-10的平方列表
l1 = [ i**2 for i in range(1,11)]
有一个列表list = [1,4,9,16,2,5,10,15],生成一个新列表。要去新列表元素是lst相邻2项的和
lst = [1,4,9,16,2,5,10,15] l2 = [lst[i]+lst[i+1] for i in range(len(lst)-1)]
用列表解析式方法打印九九乘法表:
[print('{}*{}={:<3}'.format(j,i,j*i),end='\n' if i == j else '') for i in range(1,10) for j in range(1,i+1)]
生成器表达式
语法
- (返回值 for 元素 in 可迭代对象 if 条件)
- 将列表解析式的中括号换成小括号
- 返回一个生成器
生成器和列表解析式的区别
- 生成器表达式是按需计算(或称惰性求值,延迟计算)需要的时候才计算
- 列表解析式是立即返回值
生成器
- 可迭代对象
- 迭代器
生成器表达式示例;
g = ("{:04}".format(i) for i in range(1,6))
next(g)
for x in g:
print(x)
print("-----------------------")
for x in g :
print(x)
- 生成器进行延迟计算
- 返回迭代器,可进行迭代
- 对迭代器g使用next()方法,会将g拨动一下
- 从前到后走完一遍后,不能回头
生成器和列表解析式的对比
计算方式
- 生成器表达式延迟计算,列表解析式立即计算
内存占用
- 单从返回值本身来说,生成器表达式省内存,列表解析式返回新列表
- 生成器没有数据,内存占用极小,但是使用的时候,虽然一个个返回数据,但是合起来占用内存相当
- 列表解析式构造新的列表需要占用内存
计算速度
- 单看计算时间,生成器表达式耗时非常短,列表解析式耗时长
- 但是生成器本身并没有返回任何值,只是返回了生成对象
- 列表解析式构造并返回一个新列表
集合解析式
语法
- {返回值 for 元素 in 可迭代对象 if 条件}
- 列表解析式的中括号[]换成大括号{}
- 立即返回一个集合
示例:
a = {(x,x+1) for x in range(10)}
注意,集合解析式中不能出现列表等不可hash的元素,否则编译器报错
字典解析式
语法
- {返回值 for 元素 in 可迭代对象 if 条件}
- 列表解析式的中括号[}换成大括号{}
- 使用key:value形式
- 立即返回一个字典
示例:
a = {x:(x,x+1) for x in range(5)} b = {x:[x,x+1] for x in range(5)} c = {(x,):[x,x+1] for x in range(5)}
注意,字典解析式中的key不能出现列表等不可hash的元素,否则编译器报错