列表生成式 生成器(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
25100

由于之前已经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
复制代码

 

posted @   ShineLe  阅读(389)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示