列表生成式 生成器(generator) 迭代器 yield
列表生成式
格式:通过一个或者若干个在List里边的for构建List而非List外部的for循环
举个例子:计算从1到10整数的平方构成一个List
L=[ x*x for x in range(1,11) ]
作用:①取代for循环+append快速生成一个List
②从已有的List中快速生成另一个List
补充:
1、for后可以跟 if,以达到筛选合适的元素而非全部元素以创建List
如:只取偶数
L=[ x*x for x in range(1,11) if not x%2]
注意:for后的if为筛选,不能跟else
for后的if会只筛选出符合条件的x用以构建List
for前可以跟if…else …,此时if…else…为表达式,不起筛选作用(即不会减少List中的元素个数)
L=[x if x%2 else -x for x in range(1,11)] [1, -2, 3, -4, 5, -6, 7, -8, 9, -10]
相当于
for x in range(1,11): if x % 2: #为偶数 x=x #不变 else: x=-x
2、可以两个变量同时参与
L=[ m+n for m in 'abc' for n in 'xyz']
['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']
效果类似于两层循环,第一个for对应外层循环,第二个for对应内层循环
3、当然两个变量同时参与也可以不用两个for
例如对Dict的Key和Value的访问
1 D={'Mike':23,'Bob':19,'Jim':20} 2 L=[ m+':'+str(n) for m,n in D.items()] 3 4 L 5 ['Mike:23', 'Bob:19', 'Jim:20']
注意第二行,只有相同类型才能用加号+,所以要对整数类型n进行强制类型转换
这样的话,2和3看起来就和for循环区别很小了,只是把for循环的循环体放在了for循环前边
应用:
1、用简洁的语句列出当前目录下的所有文件名
import os [D for D in os.listdir('.')] ['.idea', 'Fib.py', 'Hanoi.py', 'T1.py', 'venv']
os是模块方面的内容,以后会学到
2、将一个列表List中的所有字符串中的字符小写
方法:字符串的lower方法,str.lower(),如果是大写则是upper方法
注意,如果该List中既有字符串,又有其他类型,则需要for后if筛选
L=[ 'Abc' , 123 , 'MNO' ,True] A=[s.lower() for s in L if isinstance(s,str)] A ['abc', 'mno']
生成器
意义:生成列表List过大时,为节省空间,不把List中的每个元素都保存下来,而是根据算法,需要时通过迭代计算出指定的值
Python这种边迭代边计算的机制叫做生成器(Generator)
创建:
①把列表生成式的中括号[ ]变为小括号( )即可
G=(x*x for x in range(1,11))
②通过函数创建,利用yield关键字
如果一个函数中包含了yield关键字,那它就不是一个普通的函数,而是一个Generator。
!!!普通函数是遇到return返回,而对于Generator,是在每次调用next()方法的时候执行,遇到yield语句返回,再次执行时,从上次返回的yield语句后一句继续执行。可以理解为,yield就是generator的return
举个例子:
def odd(): print ('step 1') yield 1 print ('step 2') yield 2 print ('step 3') yield 3 o=odd() next(o) step 1 1 next(o) step 2 2 next(o) step 3 3
odd()是一个Generator,遇到next()才会执行,遇到yield就返回,每次执行都是从上次的yield处继续的。执行了3次next()后,已经没有yield了,所以再调用next()就会报错
访问元素
注意:不能通过下标 [ N ] 的方式访问generator的特定元素
①一个接一个打印
不断用next方法,python2.x中的方法是generator.next();python3.x中的方法是next(generator)
G=(x*x for x in range(1,11)) next(G) 1 next(G) 4 next(G) 9
无法next时,会抛出StopIteration错误
②for循环
Generator也是可迭代对象,可以通过for迭代
for i in G: print (i) 16 25 … 100
由于之前已经next()了3次,所以无法从头输出,只能从第四次开始
需要注意的是,用for迭代对generator进行操作,相当于进行了相同次数的next(),因此可以继续next()的次数减少了
补充:要访问某个特定元素,需要先迭代一定次数,而无法直接访问,换言之,这个元素没有保存在内存中,而是实时计算得到的
实例
Fibonacci数列:
def Fib2(num): n=1;a=0;b=1; while n<num: print (b) s=a a=b b+=s n+=1 return
Fib数列可以根据初始两个值,推算出后续任意值,这与Generator十分相似,如果我们指明是对哪个变量运用了推算规则,我们就可以把这个函数变为Generator
方法是,将print改为yield,这意味着,我们用yield标识了这个根据算法推算出来的变量b,则这个变量就是构成Generator的那个变量(这里说法不严谨,但一时找不出更适合的词语)
如果一个函数变为了Generator,我们便可以通过for循环访问其中的元素;next()也可以,但不如for简洁
for i in Fib2(6): print (i) 1 1 2 3 5
补充:Generator函数可以用一个变量承接,如
F=Fib2(6)
这样可以更直观地看出来是Generator而非普通的函数
另外,普通函数调用返回值是一个确定的值,Generator返回的是一个Generator
迭代器
可迭代对象(Iterable):可以直接用于for循环的数据类型;
两种:
1、集合类数据——Dict List Tuple Str
2、迭代器Iterator
迭代器(Iterator):可以被next( )函数调用,并不断返回下一个值的对象,直到最后抛出StopIteration错误表示无法继续返回下一个值
举例:Generator(两种:1、生成器 2、带yield的Generator函数)
可以用isinstance函数判断某数据是否为Iterable或者Iterator
#这里的A表变量,不表字母A isinstance(A , Iterable) isinstance(A , Iterator)
检查前应先从collections库中导入Iterator类
from collections.abc import Iterator
将Iterable转化为Iterator:iter()函数
from collections.abc import Iterator isinstance(iter([]),Iterator) True
Python对于Iterator的处理——当做一个数据流,只能通过next()不断返回下一个数据,它是一个惰性数列——不存储所有值,而是需要时才计算出想要的值。
Python中for循环的实质是将Iterable转化为Iterator,再通过不断的next()实现的
for x in [1,2,3,4,5]: pass #等价于 it=iter( [ 1,2,3,4,5 ] ) while True: try: x=next( it ) except StopIteration : break
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性