生成器、列表推导式和生成器表达式

生成器

生成器特点:

1. 生成器本质上迭代器

2. 生成器是自己用代码创建的

获取生成器的两种方式:

1. 生成器函数

2. 生成器表达式

yield

下面来看一个例子

 1 def func():
 2     print(111)
 3     yield 666
 4     print(222)
 5     yield 233333
 6
 7
 8 ret = func()    # 获取生成器
 9 print(ret)      # <generator object func at 0x000002B1E535B258>
10 print(type(ret))    # <class ‘generator‘>

把函数的return换成yield就可以把函数变成生成器,变成生成器后再读到函数名加括号后就不再表示执行函数而是表示获取一个生成器。变成生成器后就可以用next来取值了,来看代码

print(next(ret))   # 一个next执行一个yield(和yield之前的)

执行结果

111
666

再继续取值

1 print(next(ret))   # 111 666, 一个next执行一个yield(和yield之前的)
2 print(next(ret))   # 222 233333
3 print(next(ret))     # 超出,报错

生成器函数牢记一点:一个next只执行一个yield语句和此yield语句与上一个yield语句之间的语句

如果将yield语句赋值给某个变量会怎样,来看代码

 1 def func():
 2     print(111)
 3     a = yield 666
 4     print("a1:", a)
 5     print(222)
 6     yield 888
 7     print("a2:", a)
 8     yield 999
 9
10
11 ret = func()

执行一个next

print(next(ret))

执行结果

111
666

执行两个next

111
666
a1: None
222
888

执行三个next

print(next(ret))
print(next(ret))
print(next(ret))

结果

111
666
a1: None
222
888
a2: None
999

分析上述代码我们可以得出规律:

1. yield语句是将yield后面的值返回给next()语句

2. yield语句本身没有返回值

3. 每执行一个next语句就从上一个yield语句(不包括)开始从上往下执行

yield与return的异同:

1. return会终止函数,yield不会终止函数

2. yield和return都有返回值,yield给next()返回值,return给函数名()返回值

send

生成器函数还有一个方法:send(),send与next类似,也可以一个一个地取值,但是send还有个作用,可以传值给上一个yield(括号里写None就跟next一样)

 1 def func():
 2     a = yield 111
 3     print(a)
 4     print("mandy")
 5     b = yield 222
 6     print(b)
 7     print("sa")
 8     yield 333
 9     yield "hanser"
10
11
12 gen = func()   # 获取生成器
13 # sen不仅能对应yield取值,而且可以给上一个yield语句发送一个值
14
15 print(gen.send(None))   # 第一个send不能传值(传值为None,只取值)    111
16 print(gen.send(666))   # 两个作用:1.把666传给a;2.取值222.    666  mandy  222
17 print(gen.send("yousa"))                               # yousa  sa  333
18 print(next(gen))                                       # hanser

执行结果

111
666
mandy
222
yousa
sa
333
hanser

注意send(value)是将value传给上一个yield的yield  值这个语句,如果函数里有将yield  值赋值给某个变量,就要注意变量值的变化。代码的执行顺序是从上一个yield的后面开始,从上往下执行,最后执行当前的yield(next)。还有两点点需要注意:

1. 第一次取值不能用send传参

2. 最后一个yield永远得不到send传的值

yield from

前面的yield的返回值都是数字,如果yield的返回值是可迭代对象会有什么不同呢,一起来看

1 def func():
2     lst = [1, 2, 3, 4]
3     yield lst
4
5
6 gen = func()     # gen [[1, 2, 3, 4]]
7 print(gen)

执行结果

<generator object func at 0x0000016A300AFF68>
[1, 2, 3, 4]

用next得到的结果是一个列表,如果不用next取值,直接用for循环取值,能取到吗?来看

for i in next(gen):
    print(i)

结果

<generator object func at 0x0000024B4905FF68>
1
2
3
4

由此可以可以知道gen这个生成器类似于一个列表,里面只有一个元素也是列表,即 [[1, 2, 3, 4]],

如果把yield换成yield from,结果会是怎样的呢

1 def func():
2     lst = [1, 2, 3, 4]
3     yield from lst        # 把lst变成迭代器
4
5
6 gen = func()
7 print(next(gen))
8 print(next(gen))
9 print(next(gen))

执行结果

1
2
3

列表推导式

定义:列表推导式就是用一行代码构建简单的列表

列表推导式的三种模式

1. 循环模式

语法:[变量(加工后的变量) for 变量 in iterable]

[i for i in range(10)]

2. 筛选模式

语法:[变量(加工后的变量) for 变量 in iterable if 条件]

[i for i in range(10) if i % 2 == 0]
["地球%s号" % i for i in range(1, 50) if i % 3 == 0]

3. 三元模式(循环模式与三元运算的结合)

lst = ["$" if i % 2 == 0 else i for i in [i**2 for i in range(10)]]print(lst)

执行结果

[‘$‘, 1, ‘$‘, 9, ‘$‘, 25, ‘$‘, 49, ‘$‘, 81]

优点:节省代码

缺点:(1)只有一行,debug查不出来

   (2)不能构建复杂的列表(常规的方法可以)

生成器表达式

生成器表达式语法与列表推导式几乎一样,只是把[]换成()

1 gen = ("嫦娥%s号" % i for i in range(1, 10))
2 print(gen)
3 print(next(gen))  # 嫦娥1号
4 for i in gen:
5     print(i)     # 嫦娥2号 嫦娥3号...

执行结果

<generator object <genexpr> at 0x0000016C3625FF68>
嫦娥1号
嫦娥2号
嫦娥3号
嫦娥4号
嫦娥5号
嫦娥6号
嫦娥7号
嫦娥8号
嫦娥9号

什么时候用列表推导式,什么时候用生成器表达式?

数据量小的时候用列表推导式,数据量大的时候用生成器表达式,因为生成器表达式可以一个一个地取值,不占内存

字典推导式和集合推导式

字典推导式

字典推导式的语法和列表推导式类似,只是把变量换成键值对,[]换成{}

print({i:None for i in range(1, 10)})

结果

{1: None, 2: None, 3: None, 4: None, 5: None, 6: None, 7: None, 8: None, 9: None}

键值交换

# 键值交换
m = {"a": 10, "b": 34, "c": 88}
print({v: k for k, v in m.items()})

执行结果

{10: ‘a‘, 34: ‘b‘, 88: ‘c‘}

集合推导式

set2 = {i*3+1 for i in range(10)}
print(set2)

执行结果

set2 = {(i*3+1) % 4 for i in range(10)}
print(set2)

执行结果

{0, 1, 2, 3}

原文地址:https://www.cnblogs.com/zzliu/p/10214359.html

时间: 2024-10-06 22:28:06

生成器、列表推导式和生成器表达式的相关文章

三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

一 三元表达式.列表推导式.生成器表达式 1.三元表达式 name=input('姓名>>: ') res='SB' if name == 'alex' else 'NB' print(res) 2.列表推导式 #1.示例 egg_list=[] for i in range(10): egg_list.append('鸡蛋%s' %i) egg_list=['鸡蛋%s' %i for i in range(10)] #2.语法 [expression for item1 in iterabl

六 三元表达式、列表推导式、生成器表达式

一 三元表达式 二 列表推导式 三 生成器表达式 一 三元表达式 1 name=input('姓名>>: ') 2 res='abc' if name == 'lucy' else 'jack' 3 print(res) 二 列表推导式 #1.示例 egg_list=[] for i in range(10): egg_list.append('鸡蛋%s' %i) egg_list=['鸡蛋%s' %i for i in range(10)] #2.语法 [expression for ite

day14,列表推导式,生成器表达式,内置函数

一.列表推导式.生成器表达式: # li = []# for i in range(1,101):# li.append(i)# print(li) #l1 = [python1期,python2期,python3期.....]# l1 = []# for i in range(1,12):# l1.append('python%s期' % i)# print(l1)#一行搞定,列表推导式:用列表推导式能够构建的任何列表,用别的都可以构建.#一行,简单,感觉高端.但是,不易排错.# li = [

Python3 三元表达式、列表推导式、生成器表达式

Python3 三元表达式.列表推导式.生成器表达式 三元表达式 表达式中,有三个元素 name = input("请输入姓名: ")ret = '输入正确' if name == 'aaa' else '输入错误'print(ret)  列表推导式 #1.示例# 方法1egg_list1 = []for i in range(10): egg_list1.append('鸡蛋%s' % i)print(egg_list1) #方法2egg_list2 = ['鸡蛋%s' %i for

列表推导式和生成器表达式

# 列表推导式 lis = [i for i in range(10)] print(lis) # 生成器表达式 crt = (i for i in range(10)) print(crt) print(crt.__next__()) print(crt.__next__()) print(crt.__next__()) #打印: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <generator object <genexpr> at 0x00000188F0FED9

python 【迭代器 生成器 列表推导式】

python [迭代器  生成器  列表推导式] 一.迭代器 1.迭代器如何从列表.字典中取值的 index索引 ,key for循环凡是可以使用for循环取值的都是可迭代的可迭代协议 :内部含有__iter__方法的都是可迭代的迭代器协议 :内部含有__iter__方法和__next__方法的都是迭代器 print(dir([1,2,3])) lst_iter = [1,2,3].__iter__() print(lst_iter.__next__()) print(lst_iter.__ne

part4-2 流程控制二(循环结构,while、for循环,列表推导式、生成器推导式,常用工具函数,控制循环结构,4个简单实例)

循环语句在循环条件满足时,可反复执行某一段代码,这段被重复执行的代码称为循环体.在循环体中,需要在合适的时候把循环条件设置为假,从而结束循环:否则循环一直执行下去形成死循环.循环语句通常包含如下4个部分.(1).初始化语句(init_statements):在循环开始前执行,有一条或多条语句,用于完成一些起初始化工作.(2).循环条件(test_expression):一个布尔表达式,决定是否执行循环体.(3).循环体(body_statements):循环的主体,根据循环条件是否允许,这个代码

列表推导式与生成表达式的区别

列表推导式和生成表达式有相似,但是却有本质不不同简单的把它们之间的关系理一理吧:# 列表推导式: res=[i for i in range(6)] print(res) 结果:[0, 1, 2, 3, 4, 5] # 生成表达式: res=(i for i in range(6)) print(res) 结果:<generator object <genexpr> at 0x0000013EAD04EF68> # 总结: # 列表推导式和生成表达式相同点:内部代码结构相同 # 列

python——函数 20、三元表达式、列表推导式、生成器表达式

1.三元表达式 # 什么是三元表达式 三元:三个元素 x=1 y=2 if x>y: print(x) else : print(y) # 变为三元表达式: hhh=x if x>y else y print(hhh) # 简单明了 ———————————————————————————————————— def max2(x,y): if x>y: return x else : return y print(max2(1,5)) # 变为三元表达式: def max2(x,y): r

三元表达式、列表推导式、生成器表达式

一.三元表达式的使用 name = 'alex' age = 20 if name == 'alex' else 22 print(age) 二.列表推导式(声明式编程) l = ['alex%s' %i for i in range(10) if i > 5] print(l) 三.生成器表达式 ball = ('球%s' %i for i in range(10)) print(ball) print(next(ball)) print(list(ball)) 原文地址:https://ww