Python列表解析式及生成器
列表解析式
示例:生成一个列表,元素0~9,对每一个元素自增1后求平方返回新的列表
#使用for循环 lst = [] for i in range(10): lst.append((i+1)**2) print(lst) print('-----------------') lst = [None] * 10 for i in range(10): lst[i] = (i+1) ** 2 print(lst)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
#列表解析式 [(i+1)**2 for i in range(10)]
语法
[返回值 for 元素 in 可迭代对象 if 条件]
使用中括号[],内部是for循环,if条件语句可选
返回一个新的列表
列表解析式是一种语法糖
编译器会优化,不会因为简写而产生效率问题,反而提高了效率
减少程序员工作量,简化代码,可读性增强
在列表解析内不能嵌套多层if .... elif ..... else ......
#10以内的偶数 lst1 =[] for i in range(10): if i % 2 ==0: lst1.append(i) print(lst1) [i for i in range(10) if i % 2 ==0] #奇数 [i for i in range(10) if i % 2] #20以内能被2整数和3整除的数 lst2 = [] for i in range(20): if i %2==0 or i % 3 ==0: lst2.append(i) print(lst2) [ i for i in range(20) if i % 2 or if % 3 ] #既能被2整数又能被3整数 [i for i in range(20) if i % 2 == 0 and i % 3 == 0] [i for i in range(20) if i % 2 == 0 if i % 3 == 0] lst2 = [] for i in range(20): if i %2==0: if i % 3 ==0: lst2.append(i) print(lst2) ----------------------------- lst2 = [] for i in range(20): if i %2==0 and i % 3 ==0: lst2.append(i) print(lst2)
列表解析式进阶
循环一层层执行
[expr for i in iterable1 for j in iterable2]
等价于:
lst = []
for i in iterable1:
for j in iterable2:
lst.append(expr)
[(x,y) for x in 'abcde' for y in range(3)] [[x,y] for x in 'abcde' for y in range(3)] [{x,y} for x in 'abcde' for y in range(3)] #无序,谁在前在后不确定,生成单独的列表无需考虑去重 [{x:y} for x in 'abcde' for y in range(3)]

t1 = [(i, j) for i in range(7) if i > 4 for j in range(20,25) if j > 23] print(t1) t2 = [(i, j) for i in range(7) for j in range(20,25)if i > 4 if j > 23] print(t2) t3 = [(i, j) for i in range(7) for j in range(20,25)if i > 4 and j > 23] print(t3) #[(5, 24), (6, 24)] 结果都是这个,但是,第一种效率较高一些,提前判断进入的条件
习题地址:https://www.cnblogs.com/alrenn/p/12656465.html
生成器表达式(generator expression)
语法:
(返回值 for 元素 in 可迭代对象 if 条件)
只要将列表解析式的中括号换成小括号就是生成器表达式
返回一个生成器
和列表表达式的区别:
生成器表达式是惰性求值,按需计算,需要的时候才计算值
列表表达式是立即返回值
生成器:
可迭代
迭代器
#示例 g1 = ('{:04}'.format(i) for i in range(10)) #<generator object <genexpr> at 0x0000027CDAE77FC0> #表示是生成器对象,可迭代,可使用next()函数驱动,指针则往右移动,当指针移动到最右端时,则无法再次驱动和for迭代。 #因为生成器是无法向列表那样,一致迭代,当地址指针到了最后一个后,用next() 再迭代会报错 for x in g1: print(x) next(g1) #报错 Stop Iteration

列表解析式:
立即计算,返回的不是迭代器,返回可迭代对象列表,可迭代多次。
g2 = ['{:04}'.format(i) for i in range(10)] for x in g2: print(x) print('------------') for x in g2: print(x) #可多次迭代
注意点:
a = (print("{}".format(i+1)) for i in range(2)) first = next(a) second = next(a) val = first + second #print()函数返回的是None None + None unsupported operand type(s) for +: 'NoneType' and 'NoneType' #正确表达式 a = (i for i in range(10) if i % 2) first = next(a) second = next(a) val = first + second print(val) #4
生成器和列表解析式的对比:
计算方式:
生成器表达式延迟计算,列表解析式立即计算
内存占用:
单从返回值本身来说,生成器表达式省内存,列表解析式能返回新的列表
生成器没有数据,内存占用极少,但是使用的时候,虽然一个个返回数据,但是合起来占用的内存也差不多
列表解析式构造新的列表需要占用内存
计算速度:
单看计算时间看,生成器表达式好事非常短,列表解析式耗时长
但是生成器本身并没有返回任何值,只返回一个生成器对象
列表解析式构造并返回一个新的列
集合解析式
语法:
{返回值 for 元素 in 可迭代条件 if 条件}
列表解析式的中括号,换成大括号
立即返回一个set()集合对象,需要注意集合返回时无序
{(i,i+1) for i in range(10)}
{{i,i+1} for i in range(10)} #错误,set()不可hash
字典解析式
语法:
{返回值 for 元素 in 可迭代条件 if 条件}
列表解析式的中括号,换成大括号
使用key:value形式
立即返回一个dict对象
{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)} #错误表达,key不可hash

浙公网安备 33010602011771号