Python迭代器、列表解析、生成器

1.列表生成式:

[expr for iter_var in iterable]

[expr for item in iterable if cond1 if cond2] 

[expr for i in iterable1 for j in iterable2 ] 

2.生成器是小括号(),要用next()来访问

与列表解析式截然不同,列表解析式是立即返回一个完整的列表,生成器表达式是按需计算,惰性求值,需要是才进行求值

具有yield关键字的函数都是生成器,yield可以理解为return,返回后面的值给调用者。不同的是return返回后,函数会释放,而生成器则不会。在直接调用next方法或用for语句进行下一次迭代时,生成器会从yield下一句开始执行,直至遇到下一个yield。

题目:

python2和python3的range(100)的区别

python2返回列表,python3返回迭代器,节约内存

Python迭代器、列表解析、生成器

迭代器(iterator)

  迭代器用来为类序列对象提供一个类序列的接口。迭代器就是生成一个有next()方法的对象,而不是通过索引来计数。

  序列、字典、文件中当使用for x in y的结构时,其实质就是迭代器,迭代器是和实际对象绑定在一起的,所以在使用迭代器时或者上述3者时不能修改可变对象的值。这会产生错误。如:在使用for x in y的结构来遍历字典时删除符合条件的字典内容,这会导致报错。

  创建迭代器的方法:iter(object)和iter(func,sentinel)两种。一种使用的是序列,另一种使用类来创建。

列表解析(List comprehensions)

  主要用来动态的创建列表,和map()、filter()和reduce()一样可以用来产生列表。和生成器不同的是,列表解析一次生成一个列表,所占内存较大。

[expr for iter_var in iterable]

即 [返回值 for 元素 in 可迭代对象] 
工作过程: 
- 迭代iterable中的每个元素; 
- 每次迭代都先把结构赋值给iter_var,然后通过exp得到一个新的返回值; 
- 最后将返回值形成一个新的列表。 

条件语法格式
[expr for item in iterable if cond1 if cond2] 
工作过程:

迭代iterable中的每一个元素,然后对每个元素进行if条件判断,当有多个if时,if条件相当于if cond1 and if cond 2
将迭代的结果复制给item,然后通过expr表达式计算出返回值
将返回值形成新的列表 
代码示范:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [x for x in range(1,20) if x>=10 if x%2==0]
print(lst)
运行结果:
[10, 12, 14, 16, 18]
1
2
3
4
5
6
嵌套循环语法
[expr for i in iterable1 for j in iterable2 ] 
工作过程:

迭代iterable1中的第一个元素后,进入下一轮for循环迭代iterable2中的每一元素,interable2循环完成后,再次进入iterable1中的第二个元素,以此类推。
把迭代结果赋值给iter_var,荣光expr得到返回值
最后将返回值形成新的对象list 
代码示范:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst0 = [(x,y) for x in 'abc' for y in range(2)]
lst1 = [[x,y] for x in 'abc' for y in range(2)]
lst2 = [{x,y} for x in 'abc' for y in range(2)]
print(lst0)
print(lst1)
print(lst2)
运行结果:
[('a', 0), ('a', 1), ('b', 0), ('b', 1), ('c', 0), ('c', 1)]
[['a', 0], ['a', 1], ['b', 0], ['b', 1], ['c', 0], ['c', 1]]
[{0, 'a'}, {1, 'a'}, {0, 'b'}, {1, 'b'}, {0, 'c'}, {1, 'c'}]

打印九九乘法表
考点 
- 严格按照工作过程和列表解析式的定义,套用至少一个for循环或多个for循环 
- for循环必须是连续在一起的,for循环不能分开 
正确示范代码:

#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [print("{}*{}={:<3}{}".format(j,i,j*i,"\n" if i==j else ""),end="") for i in range(1,10) for j in range(1,i+1)]
print(lst)
运行结果:
1*1=1  
1*2=2  2*2=4  
1*3=3  2*3=6  3*3=9  
1*4=4  2*4=8  3*4=12 4*4=16 
1*5=5  2*5=10 3*5=15 4*5=20 5*5=25 
1*6=6  2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 
1*7=7  2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 
1*8=8  2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 
1*9=9  2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
--------------------- 

 

生成器

生成器的构成


生成器的构成是通过两种方式: 
- 使用类似列表的方式生成 
具体信息如下: 
1.语法格式(返回值 for 元素 in 可迭代对象 if条件
2.列表解析式的中括号换成小括号即可 
3.返回一个生成器 
- 使用包含yield的函数来生成 
通常情况下对应简单的列表等采用列表生成器,若遇到复杂的计算值采用yield函数构成

生成器的执行过程与特性


执行过程: 
在执行过程中,遇到yield关键字就会终端执行,下次继续从中断位置开始执行。 
特性: 
1.与列表解析式截然不同,列表解析式是立即返回一个完整的列表,生成器表达式是按需计算,惰性求值,需要是才进行求值; 
2.遇到yield记录当前位置,下次从记录位置继续执行 
3.从前到后走完一遍后,不能回头

 

具有yield关键字的函数都是生成器,yield可以理解为return,返回后面的值给调用者。不同的是return返回后,函数会释放,而生成器则不会。在直接调用next方法或用for语句进行下一次迭代时,生成器会从yield下一句开始执行,直至遇到下一个yield。

生成器值的访问方式


通过内置next()方法访问
使用循环方式进行迭代
调用生成器对象send()方法

#!/bin/python3
#-*- coding: UTF-8 -*-
g = ("{:04}".format(i) for i in range(1,6))
print(next(g))
for x in g:
    print(x)
print('~~~~~~~~~~~~')
for x in g:
    print(x)
运行结果:
0001
0002
0003
0004
0005

~~~~~~~~~~~~
原文:https://blog.csdn.net/xuexiaoyaani/article/details/79836630 

练习,使用文件读取,找出文件中最长的行的。最精简答案:max(len(x.strip()) for x in open('/etc/motd','r'))