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 

 

posted @ 2020-04-06 21:44  Alrenn  阅读(436)  评论(0)    收藏  举报