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返回迭代器,节约内存
迭代器(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.****.net/xuexiaoyaani/article/details/79836630
练习,使用文件读取,找出文件中最长的行的。最精简答案:max(len(x.strip()) for x in open('/etc/motd','r'))