python学习之生成器
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学习之生成器的更多相关文章
- Python学习二(生成器和八皇后算法)
看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...
- python学习之---生成器
通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含1000万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元 ...
- Python学习笔记 - 生成器generator
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # generator 生成器 L = [x * x for x in range(10)] print( ...
- Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
- python学习-39 生成器总结
总结 1.语法上和函数类似:生成器函数和常规函数几乎是一样的.它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,常规函数使用return语句返回一个值. 2.自动实现迭代器 ...
- python学习之- 生成器/迭代器
列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...
- Python学习---装饰器/迭代器/生成器的学习【all】
Python学习---装饰器的学习1210 Python学习---生成器的学习1210 Python学习---迭代器学习1210
- Python学习笔记之生成器、迭代器和装饰器
这篇文章主要介绍 Python 中几个常用的高级特性,用好这几个特性可以让自己的代码更加 Pythonnic 哦 1.生成器 什么是生成器呢?简单来说,在 Python 中一边循环一边计算的机制称为 ...
- python学习10—迭代器、三元表达式与生成器
python学习10—迭代器.三元表达式与生成器 1. 迭代器协议 定义:对象必须提供一个next方法,执行该方法或者返回迭代中的下一项,或者返回一个StopIteration异常,以终止迭代(只能往 ...
随机推荐
- ionic实现下载文件并打开功能(file-transfer和file-opener2插件)
作为一款app,下载文件功能,和打开文件功能,在某些场景下还是十分有必要的.使用cordova-plugin-file-transfer和cordova-plugin-file-opener2这两个插 ...
- 关于distinct的compare参数的使用
1.创建compare类 using DCZY.Bean; using System; using System.Collections.Generic; using System.Linq; usi ...
- Oracle存储结构-段区块
段 一个段建立以后首先会分配一个区,区中包括含8个块,这时执行insert插入数据,当这个区写满后,会在分配一个区 1.一个段建立以后,Oracle如何给段分配区? 2.段分配到区以后,有了空闲空间, ...
- ES6 Promise使用介绍
1.什么是Promise Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大. 这么说可能不够直观的理解,看下面的两个例子 // callback回调函数 ...
- THUWC 2019游记
坑先占着QwQ 不太喜欢写Blog, 因此我的Blog一直很冷清,但是还是想写写这种游记啦,反正是给自己看的 Day -4 颓了一整天,一道题都没写 于是无聊用GL写了一个海战游戏,让两个程序对打-- ...
- Unity3D_(游戏)双人3D坦克_简易版
双人3D坦克实现 player1: WSAD控制上下左右 空格键发射炮弹 player2: IKJL可控制上下左右 B键发射炮弹 每个坦克只有100hp,子弹击中1次扣30hp,hp时时显示在坦克上 ...
- 把execel表数据导入mysql数据库
今天,是我来公司第二周的第一天. 作为新入职的实习生,目前还没适合我的实质项目工作,今天的学习任务是: 把execel表数据导入到mysql数据库,再练习下java操作JDBC. 先了解下execel ...
- LinkedList类源码浅析(二)
1.上一节介绍了LinkedList的几个基本的方法,其他方法类似,就不一一介绍: 现在再来看一个删除的方法:remove(Object o) remove方法接受一个Object参数,这里需要对参数 ...
- HBuilder搭建Android模拟器
HBuilder搭建Android模拟器 //来源: https://www.cnblogs.com/bjxingch/articles/6657938.html 1.下载夜神Android模拟 ...
- 堆里面的分区:Eden,Survivor(from+ to),老年代,各自的特点
堆里面分为新生代和老生代(java8取消了永久代,采用了Metaspace),新生代包含Eden+Survivor区,survivor区里面分为from和to区,内存回收时,如果用的是复制算法,从fr ...