4.6 生成器Generrator

​ 生成器本质就是迭代器。python社区生成器与迭代器是一种。

​ 生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的

4.6.1生成器初识

python中的生成器:

​ 1.生成器函数:使用yield语句而不是使用return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数状态,下次可以从它离开的地方继续执行,一个next引导一个yield。

​ 2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一个对象而不是一次构建一个结果列表。

本质:迭代器(自带_itr_ 和_next_方法)

特点:惰性运算

​ 3.利用python提供的一些内置函数,返回一个生成器

4.6.2 生成器函数

​ 一个包含yield关键字的函数就是一个生成器函数,用next触发,一个next对应一个yield。 只要函数中出现了yield那么他就不是函数,它是生成器函数。

def func():
yield 2, 3, 4
yield 'a'
yield [1,2,3]
ret = func() #注释1:
print(ret) #注释2:
print(next(ret))
print(next(ret))
print(next(ret))
#输出
<generator object func at 0x000001EB854B3FC0>
(2, 3, 4)
a
[1, 2, 3]

注释1:生成器对象,这里一定要声明一个变量指向生成器,直接print生成器的话,相当于在内存中新开辟空间调用生成器,print一次func() 就建立一个新的生成器,类似于多条产线同时生产一个物品一样,所以必须要有一个变量来指向生成器地址,目的是利用变量的唯一性特点。

注释2:print(ret)只是打印的ret指向的生成器地址,要显示生成器的结果,要用next来取值

4.6.3 yield 与 return的区别

​ return一般在函数中只设置一个,他的作用是终止函数,并且给函数的执行者返回值。

​ yield在生成器函数中可设置多个,他并不会终止函数,next会获取对应yield生成的元素。

4.6.4 send(了解)

send和next()区别:

​ 相同点:

​ send 和 next()都可以让生成器对应的yield向下执行一次。

​ 都可以获取到yield生成的值。

​ 不同点:

​ 第一次获取yield值只能用next不能用send(可以用send(None))。

​ send可以给上一个yield置传递值。

4.6.5 生成器举例

#1:单线程
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1 #即使yield在
s = eat_food()
print(next(s)) #输出['1份菜']
print(next(s)) #输出['1份菜', '2份菜'] #2:多线程,
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1
s = eat_food()
s1 = eat_food() #多线程下,交叉next不会冲突
print(next(s)) #输出['1份菜']
print(next(s1)) #输出['1份菜']
print(next(s)) #输出['1份菜', '2份菜']
print(next(s1)) #输出['1份菜', '2份菜'] #next配合for循环连续输出
def eat_food():
lis1 = []
for i in range(1,2001):
lis1.append(f"{i}份菜")
yield lis1
s = eat_food()
for i in range(200): #一次性输出200次
print(next(s))

4.6.6 yield与yield from

yield form可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回。(python3中特有)

#先看yield
def func():
li = [1,2,3]
yield li
a = func()
print(next(a)) #输出[1, 2, 3] #再看yield form
def func():
li = [1,2,3]
yield from li #将一个可迭代对象的每一个元素返回给next
a = func()
print(next(a)) #输出 1
print(next(a)) #输出 2
print(next(a)) #输出 3

有个小坑,yield from 是将列表中的每一个元素返回,所以如果写两个yield from 并不会产生交替的效果

def func():
lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
lst2 = ['馒头', '花卷', '豆包', '大饼']
yield from lst1 #输出玩lst1才能输出lst2
yield from lst2
g = func()
for i in g:
print(i)

4.6.7 列表推导式,生成器推导式

1.列表推导式
  • 列表推导式:一行代码构建一个有规律比较复杂的列表。
  • 列表推导式与之前写法对比
#普通表达式
#生成1-100的列表l1 = [1,2,3......100]
l1 = []
for i in range(1,101):
l1.append(i)
print(l1)
# 列表推导式
l1 = [i for i in range(1, 101)]
print(l1)
2.列表推导式的两种构建方式
  • ​ 循环模式: [变量(加工后的变量) for 变量 in iterable]
  • ​ 筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]
# ----------------循环模式:------------

# 将10以内所有整数的平方写入列表。
print([i**2 for i in range(1, 11)])
# 100以内所有的偶数写入列表.
print([i for i in range(2, 101, 2)])
# 从python1期到python100期写入列表list
print([f'python{i}期' for i in range(1, 101)])
# ---------------筛选模式-------------:

# 三十以内可以被三整除的数。
print([i for i in range(1, 31) if i % 3 == 0])
# 过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
l1 = ['barry', 'fdsaf', 'alex', 'sb', 'ab']
print([i.upper() for i in l1 if len(i) > 3])
# 找到嵌套列表中名字含有两个‘e’的所有名字(有难度)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
print([j for i in names for j in i if j.count('e') > 1])

列表推导式的优缺点:

优点:

简单,快捷,装b。

缺点:

​ 可读性不高,不好排错。

​ 慎用,不要入迷。

3.生成器推导式

与列表推导式几乎一模一样,只是把[]换成()就行了。

循环模式,筛选模式。

#循环模式
tem = (i for i in range(10))
print(next(tem)) #输出 0
print(next(tem)) #输出 1
#筛选模式
tem = (i for i in range(10) if i%2==1)
print(next(tem)) #输出 1
print(next(tem)) #输出 3
#触发生成器
tem = (i for i in range(10) if i%2==1)
for i in tem:
print(i)

出发迭代器的几种方式:

​ 1.next(tem)触发

​ 2.for i in tem:

​ print(i)

​ 因为for循环内部调用了next函数

​ 3.转换生列表

​ print(list(tem))以列表的形式输出

4.6.8 字典推导式、集合推导式

两种模式: 循环模式,筛选模式

# 字典推导式
l1 = ['小潘', '小明','小红', '小强']
dic = {i:l1[i] for i in range(len(l1))}
print(dic)
#集合推到式
l1 = ['小潘', '小明','小红', '小强']
set1 = {i for i in range(len(l1))}
print(set1)

python学习之生成器的更多相关文章

  1. Python学习二(生成器和八皇后算法)

    看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...

  2. python学习之---生成器

    通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含1000万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元 ...

  3. Python学习笔记 - 生成器generator

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- # generator 生成器 L = [x * x for x in range(10)] print( ...

  4. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  5. python学习-39 生成器总结

    总结 1.语法上和函数类似:生成器函数和常规函数几乎是一样的.它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,常规函数使用return语句返回一个值. 2.自动实现迭代器 ...

  6. python学习之- 生成器/迭代器

    列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...

  7. Python学习---装饰器/迭代器/生成器的学习【all】

    Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210

  8. Python学习笔记之生成器、迭代器和装饰器

    这篇文章主要介绍 Python 中几个常用的高级特性,用好这几个特性可以让自己的代码更加 Pythonnic 哦 1.生成器 什么是生成器呢?简单来说,在 Python 中一边循环一边计算的机制称为 ...

  9. python学习10—迭代器、三元表达式与生成器

    python学习10—迭代器.三元表达式与生成器 1. 迭代器协议 定义:对象必须提供一个next方法,执行该方法或者返回迭代中的下一项,或者返回一个StopIteration异常,以终止迭代(只能往 ...

随机推荐

  1. poi导出excel数据量过大

    问题:使用poi导出excel,数据量过大导致内存溢出 解决思路:1.多sheet导出 2.生成多个excel打包下载 3.生成csv下载 本文使用的是第二个思路,代码如下: poiUtil工具类 p ...

  2. Axure案例:用中继器实现便捷好用的3级菜单--转载

    提示1:本篇教程可能不太适合新手,以及不了解中继器.全局变量.系统变量等使用的…新手 提示2:文字其实不多,截图太多,所以看上去很长,也可直接翻到末尾查看所有的用例,其实并不多 之前有介绍过使用中继器 ...

  3. 自我介绍 & 友链

    "Never say never until the very end." --Flere825 想了想其实没什么可介绍的--毕竟我这么菜也没多少人认识我qwq还是写一点吧. 某弱 ...

  4. 使用Vue自定义组件时,报did you register the component correctly? For recursive components, make sure to provide the "name" option.(未注册组件)的原因之一

    错误信息: [Vue warn]: Unknown custom element: <list> - did you register the component correctly? F ...

  5. php面向对象相关技术

    step1 一个经典类的设计和实例化 <?php class mycoach { public $_name=''; public $_age=''; public $_expert=array ...

  6. C# 扩展方法——去重(Distinct)

    其他扩展方法详见:https://www.cnblogs.com/zhuanjiao/p/12060937.html IEnumerable的Distinct扩展方法,当集合元素为对象时,可用于元素对 ...

  7. 直通BAT必考题系列:深入详解JVM内存模型与JVM参数详细配置

    VM基本是BAT面试必考的内容,今天我们先从JVM内存模型开启详解整个JVM系列,希望看完整个系列后,可以轻松通过BAT关于JVM的考核. BAT必考JVM系列专题 1.JVM内存模型 2.JVM垃圾 ...

  8. string、wstring、CString 相互转换

    关于string wstring cstring的功能这里不详细叙述了 可参见这里:https://www.cnblogs.com/guolixiucai/p/4716521.html 关于转换这里只 ...

  9. HDU2433—Travel (BFS,最短路)

    Travel Time Limit: 10000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  10. 安装破解confluence6.7.1(插图丢了,一直懒得补)

      JIRA安装:https://www.cnblogs.com/wei9593/p/10194784.html 1环境: centos7.2 java-1.8https://www.cnblogs. ...