python学习第11天----生成器、生成器函数、推导式、生成器表达式

1.生成器(generator)

  生成器的本质就是迭代器

1)生产器的三种生成方法

①通过生成器函数

②通过生成器表达式创建生成器

③通过数据转换

2.生成器函数

1)函数中包含了关键字yield,当前这个函数就不再是普通的函数了,而是一个生成器函数;此执行这个函数(即调用),只会获取到生成器,而不是去执行这个函数

def func():
    print("九尾妖狐")
    yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
func()      #不再是执行函数,而是通过func()来创建一个生成器
print(func())
输出:
<generator object func at 0x000001A3D0380AF0>
View Code

#生成器的本质是迭代器,所以可以以迭代器的方式使用生成器

def func():
    print("九尾妖狐")
    yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
g = func()      #不再是执行函数,而是通过func()来创建一个生成器
print(g.__next__())
输出:
九尾妖狐
阿狸
View Code

2)return是直接返回函数的结果,结束函数的调用;yield也是返回结果,但会继续往下执行,可以让函数分段执行

def func():
    print("九尾妖狐")
    yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
    print("远古巫灵")
    yield "泽拉斯"
    print("无双剑姬")
    yield "菲奥娜"
g = func()      #不再是执行函数,而是通过func()来创建一个生成器
print(g.__next__())
print(g.__next__())
print(g.__next__())
输出:
九尾妖狐
阿狸
远古巫灵
泽拉斯
无双剑姬
菲奥娜
View Code

#注:生成器函数中,最后一个yield后面的内容,会被执行到,但是会报错(StopIteration),所以在最后一个yield之后,是不写代码的(最后一个yield后,再进行__next__()会报错)

3.send方法

1)__next__()方法和send()方法的共同点和区别

①共同点:__next__()可以让生成器向下执行一次;send()也可以让生成器向下执行一次

def func():
    print("九尾妖狐")
    yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
    print("远古巫灵")
    yield "泽拉斯"
    print("无双剑姬")
    yield "菲奥娜"
g = func()      #不再是执行函数,而是通过func()来创建一个生成器
print(g.__next__())
print(g.send(1))
print(g.__next__())
输出:
九尾妖狐
阿狸
远古巫灵
泽拉斯
无双剑姬
菲奥娜
View Code

②区别:send()该可以给上一个yield传一个值;但是不能给最后一个yield发送值,否则会报错,在第一次执行生成器的时候,只能使用__next__(),不能使用send(), 因为此时没有上一个yield

def func():
    print("九尾妖狐")      #黄色区域表示第一个__next__()的执行
    a = yield "阿狸"      #send传入的值赋值给了a
    print(a)            #a的值由send传入
    print("远古巫灵")
    b = yield "泽拉斯"     #蓝色区域为send()的执行
print(b)
    print("无双剑姬")
    c = yield "菲奥娜"      #灰色区域为下一个send()执行
g = func()      #不再是执行函数,而是通过func()来创建一个生成器
print(g.__next__())
print(g.send(666))
print(g.send(999))
输出:
九尾妖狐
阿狸
666
远古巫灵
泽拉斯
999
无双剑姬
菲奥娜
View Code

例:将生成器转换对象转化为一个列表

def func():
    yield 11
    yield 12
    yield 13
    yield 44
g = func()
lst = list(g)
print(lst)
输出:
[11, 12, 13, 44]
View Code

4.推倒式

1)引入:生成一个列表,里面装1-14的数据

lst = []
for i in range(1,15):
    lst.append("python%s" % i)
print(lst)
输出:
['python1', 'python2', 'python3', 'python4', 'python5', 'python6', 'python7', 'python8', 'python9', 'python10', 'python11', 'python12', 'python13', 'python14']
View Code

2)列表推导式完成上述要求

①语法

[最终结果(变量) for 变量 in 可迭代对象]

②完成上述要求

lst = ["python%s" % i for i in range(1,15)]
print(lst)
输出:
['python1', 'python2', 'python3', 'python4', 'python5', 'python6', 'python7', 'python8', 'python9', 'python10', 'python11', 'python12', 'python13', 'python14']
View Code

③纯数字

lst = [ i for i in range(1,15)]
print(lst)
输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
View Code

④练习:

#获取1-100内能被3整数的数

lst = [i for i in range(1,101) if i%2 ==0 ]
print(lst)
输出:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]
View Code

#获取100以内能被3整除的数的平方

lst = [i*i for i in range(1,101) if i%3==0]
print(lst)
输出:
[9, 36, 81, 144, 225, 324, 441, 576, 729, 900, 1089, 1296, 1521, 1764, 2025, 2304, 2601, 2916, 3249, 3600, 3969, 4356, 4761, 5184, 5625, 6084, 6561, 7056, 7569, 8100, 8649, 9216, 9801]
View Code

#寻找名字中带有两个e的名字

names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,
'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]
lst = [name for first in names for name in first if name.count("e")==2]
print(lst)
输出:
['Jefferson', 'Wesley', 'Steven', 'Jennifer']
View Code

总结:其他的东西正常写,只是把最终的结果提到了前面

5.生成器表达式

 1)生成器表达式和列表推导式的语法基本一昂,只是把[]换成了();这时候产生的就不再是一个列表,而是一个生成器

g = (i for i in range(1,10))
print(g)           #g为生成器对象,就生成器表达式生成
print(g.__next__())
print(list(g)
输出:
<generator object <genexpr> at 0x00000168E5FA0D00>
1
[2, 3, 4, 5, 6, 7, 8, 9]
View Code

#循环输出整个生成器

g = (i for i in range(1,10))
for el in g:
    print(el)
1
。
。
9
View Code

2)生成器表达式和列表推导式的区别

①列表推导式比较耗费额你存,一次性加载。生成器表达式几乎不占用内存,使用的时候才分配和使用内存

②得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器

3)生成器的惰性机制:生成器只有在访问的时候才取值,即找它要才给你值,不找它要,就不会执行;

         同样一篮子鸡蛋,列表推导式:直接拿到一篮子鸡蛋;生成器表达式:拿到一个老母鸡,需要急待就给你下蛋

def func():
    print(111)
    yield 222
g = func() # ⽣成器g
g1 = (i for i in g) # ⽣成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) # ⽣成器g2. 来源g1
print(list(g)) # 获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕.
print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据
print(list(g2)) #和g1同理
输出:
111
[222]
[]
[]
View Code

6.字典推导式

#将字典中的key和value互换

dic = {'a':"张三",'b':"李四"}
dic_new = {dic[key]:key for key in dic}
print(dic_new)
输出:
{'张三': 'a', '李四': 'b'}
View Code

#将lst1列表中的值作为key;lst2列表中的值作为value,生成一个字典

lst1 = ["LOL","CF","DNF","qqfeiche"]
lst2 = ["英雄联盟","穿越火线","地下城与勇士","QQ飞车"]
dic = {lst1[i]:lst2[i] for i in range(len(lst1))}
print(dic)
输出:
{'CF': '穿越火线', 'LOL': '英雄联盟', 'qqfeiche': 'QQ飞车', 'DNF': '地下城与勇士'}
View Code

7.集合推导式

         集合推导式可以直接生成一个集合;集合的特点的是无序,不重复;所以集合推导式自带去重功能

lst = ["九尾妖狐","远古巫灵","九尾妖狐","惩戒之箭"]
s = {i for i in lst}      #集合推导式
print(s)
输出:
{'惩戒之箭', '远古巫灵', '九尾妖狐'}
View Code

总结:推导式有列表推导式、字典推导式、集合推导式,但是没有元组推导式

         生成器表达式:(结果 for 变量 in 可迭代对象 if 条件筛选)

         生成器表达式可以直接获取到生成器对象,生成器对象可以直接进行for许纳湖按,生成器具有惰性机制

例:

def add(a, b):
    return a + b
def test():
    for r_i in range(4):
        yield r_i
g = test()
for n in [2, 10]:
    g = (add(n, i) for i in g)
    # g = (add(n, i) for i in add(n, i) for i in g)
    # g = (add(n, i) for i in add(n, i) for i in test())
    # g = (add(n, i) for i in add(n, i) for i in [0,1,2,3])
    # g = (add(10, i) for i in add(10, i) for i in [0,1,2,3])
    # g = (add(10, i) for i [10,11,12,13])

print(list(g))
输出:
[20, 21, 22, 23]
View Code

8.练习

1)用推导式完成:过滤掉长度小于3的字符串列表,并将剩下的转化成大写字母

lst = ["apple","bababa","dog","pig","orange"]
lst_new = [el.upper() for el in lst if len(el) > 3 ]
print(lst_new)
输出:
['APPLE', 'BABABA', 'ORANGE']
View Code

2)推导式完成:求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表

lst = [(x,y) for x in range(5) if x%2==0 for y in range(5) if y%2==1]
print(lst)
输出:
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
View Code

3)推导式完成:求M中3,6,9组成的列表M=[[1,2,3],[4,5,6].[7,8,9]]

M=[[1,2,3],[4,5,6],[7,8,9]]
lst = [i[2] for i in M]
print(lst)
输出:
[3, 6, 9]
View Code

#倒着推导

M = [3, 6, 9]
lst = [[i-2,i-1,i] for i in M]
print(lst)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
View Code

4)推导式:求出50以内能被3整除的数的平方,并放入到一个列表中

lst = [i*i for i in range(50) if i%3==0]
print(lst)
输出:
[0, 9, 36, 81, 144, 225, 324, 441, 576, 729, 900, 1089, 1296, 1521, 1764, 2025, 2304]
View Code

5)推导式构建一个列表[0,2,4,6,8,10,12,14,16,18]

lst = [i for i in range(0,20,2)]
print(lst)
输出:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
View Code
原文地址:https://www.cnblogs.com/piaolaipiaoqu/p/13851521.html