正文
python函数-迭代器&生成器
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
python函数-迭代器&生成器
一、迭代器
1 可迭代协议
-
迭代:就是类似for循环,将某个数据集内的数据可以“一个挨着一个取出来”
-
可迭代协议:
1 可迭代协议
-
迭代:就是类似for循环,将某个数据集内的数据可以“一个挨着一个取出来”
-
可迭代协议:
① 协议内容:内部实现__iter__方法
② 验证方法:dir()方法。通过dir()方法查看是否含有__iter__方法
③ __iter__方法的作用:可迭代的数据类型执行__iter__方法后会生成一个迭代器对象
print([1,2].__iter__()) 结果
<list_iterator object at 0x1024784a8>
2 迭代器协议
1 引出
'''
dir([1,2].__iter__())是列表迭代器中实现的所有方法,dir([1,2])是列表中实现的所有方法,都是以列表的形式返回给我们的,为了看的更清楚,我们分别把他们转换成集合,
然后取差集。
'''
#实现的所有方法
print(dir([1,2].__iter__()))
print(dir([1,2]))
#取差集
print(set(dir([1,2].__iter__()))-set(dir([1,2]))) 结果:
{'__length_hint__', '__next__', '__setstate__'}
我们看到在列表迭代器中多了三个方法,那么这三个方法都分别做了什么事呢?
iter_l = [1,2,3,4,5,6].__iter__()
#获取迭代器中元素的长度
print(iter_l.__length_hint__())
#根据索引值指定从哪里开始迭代
print('*',iter_l.__setstate__(4))
#一个一个的取值
print('**',iter_l.__next__())
print('***',iter_l.__next__())
在这三个方法中,能让我们一个一个取值的神奇方法是谁???答案就是__next__
在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。那接下来我们就用迭代器的 next方法来写一个不依赖for的遍历。
l = [1,2,3,4]
l_iter = l.__iter__()
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
这是一段会报错的代码,如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常 StopIteration,告诉我们,列表中已经没有有效的元素了。这个时候,我们就要使用异常处理机制来把这个异常处理掉。
l = [1,2,3,4]
l_iter = l.__iter__()
while True:
try:
item = l_iter.__next__()
print(item)
except StopIteration:
break
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
注意: range()
print('__next__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__
print('__iter__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__ from collections import Iterator
print(isinstance(range(100000000),Iterator)) #验证range执行之后得到的结果不是一个迭代器
range()是一个可迭代的,不是一个迭代器
二、生成器
我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。
如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。
1.初识生成器
Python中提供的生成器:
- 生成器函数:常规的函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从他离开的地方继续执行。
- 生成器表达式:类似于列表推导,但是,生成器返回按需生产结果的一个对象,而不是一次构建一个结果列表
生成器的本质:
本质:迭代器(就是自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
2.生成器函数
一个含有yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
import time
def genrator_fun1():
a =
print('现在定义了a变量')
yield a
b =
print('现在又定义了b变量')
yield b g1 = genrator_fun1()
print('g1 : ',g1) #打印g1可以发现g1就是一个生成器
print('-'*) #我是华丽的分割线
print(next(g1))
time.sleep() #sleep一秒看清执行过程
print(next(g1))
初识生成器
生成器有什么好处呢?就是不会一下子在内存中生成太多数据
假如我想让工厂给学生做校服,生产2000000件衣服,我和工厂一说,工厂应该是先答应下来,然后再去生产,我可以一件一件的要,也可以根据学生一批一批的找工厂拿。
而不能是一说要生产2000000件衣服,工厂就先去做生产2000000件衣服,等回来做好了,学生都毕业了。。。
#初识生成器二 def produce():
"""生产衣服"""
for i in range():
yield "生产了第%s件衣服"%i product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num =
for i in product_g: #要一批衣服,比如5件
print(i)
num +=
if num == :
break #到这里我们找工厂拿了8件衣服,我一共让我的生产函数(也就是produce生成器函数)生产2000000件衣服。
#剩下的还有很多衣服,我们可以一直拿,也可以放着等想拿的时候再拿
初识生成器二
import time def tail(filename):
f = open(filename)
f.seek(, ) #从文件末尾算起
while True:
line = f.readline() # 读取文件中新的文本行
if not line:
time.sleep(0.1)
continue
yield line tail_g = tail('tmp')
for line in tail_g:
print(line)
生成器监听文件输入的例子
-
send
def generator():
print(123)
content = yield 1
print('=======',content)
print(456)
yield2 g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello') #send的效果和next一样
print('***',ret) #send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
def averager():
total = 0.0
count =
average = None
while True:
term = yield average
total += term
count +=
average = total/count g_avg = averager()
next(g_avg)
print(g_avg.send())
print(g_avg.send())
print(g_avg.send())
计算移动平均值
def init(func): #在调用被装饰生成器函数的时候首先用next激活生成器
def inner(*args,**kwargs):
g = func(*args,**kwargs)
next(g)
return g
return inner @init
def averager():
total = 0.0
count =
average = None
while True:
term = yield average
total += term
count +=
average = total/count g_avg = averager()
# next(g_avg) 在装饰器中执行了next方法
print(g_avg.send())
print(g_avg.send())
print(g_avg.send())
计算移动平均值(2)_预激协程的装饰器
- yield from
def gen1():
for c in 'AB':
yield c
for i in range():
yield i print(list(gen1())) def gen2():
yield from 'AB'
yield from range() print(list(gen2()))
yield from
三、列表推导式和生成器表达式
引出:
egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析
print(egg_list) >>>
['鸡蛋0', '鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9']
#峰哥瞅着alex下的一筐鸡蛋,捂住了鼻子,说了句:哥,你还是给我只母鸡吧,我自己回家下 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
print(laomuji)
print(next(laomuji)) #next本质就是调用__next__
print(laomuji.__next__())
print(next(laomuji)) >>>
<generator object <genexpr> at 0x0000000001E00DB0>
鸡蛋0
鸡蛋1
鸡蛋2
总结:
1.把列表解析的 [ ] 换成( )得到的就是生成器表达式
2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
sum(x ** 2 for x in range(4))
而不用多此一举的先构造一个列表:
sum([x ** 2 for x in range(4)])
更多精彩请见——迭代器生成器专题:http://www.cnblogs.com/a438842265/p/8551306.html
python函数-迭代器&生成器的更多相关文章
-
Python函数04/生成器/推导式/内置函数
Python函数04/生成器/推导式/内置函数 目录 Python函数04/生成器/推导式/内置函数 内容大纲 1.生成器 2.推导式 3.内置函数(一) 4.今日总结 5.今日练习 内容大纲 1.生 ...
-
【python】迭代器&生成器
源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...
-
【Python】 迭代器&生成器
迭代器 任何一个类,只要其实现了__iter__方法,就算是一个可迭代对象.可迭代对象的__iter__方法返回的对象是迭代器,迭代器类需要实现next方法.一般来说,实现了__iter__方法的类肯 ...
-
Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
-
day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包
内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...
-
函数---迭代器&生成器&列表解析&三元表达式
可迭代对象:obj.__iter__ 迭代器:iter1=obj.__iter() 1iter1.__next__ 2iter2.__next__ 迭代器: 优点:不依赖索引 ...
-
Python函数(十一)-生成器
首先看一下什么是列表生成式 >>> [i*2 for i in range(10)] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] >>> ...
-
python之迭代器 生成器 枚举 常用内置函数 递归
迭代器 迭代器对象:有__next__()方法的对象是迭代器对象,迭代器对象依赖__next__()方法进行依次取值 with open('text.txt','rb',) as f: res = f ...
-
Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
随机推荐
-
【剑指Offer面试编程题】题目1372:最大子向量和--九度OJ
题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但 ...
-
storm的JavaAPI运行报错
报错:java.lang.NoClassDefFoundError: org/apache/storm/topology/IRichSpout 原因:idea的bug:本地运行时设置scope为pro ...
-
day11-Python运维开发基础(迭代器与可迭代对象、高阶函数)
1. 迭代器与可迭代对象 # ### 迭代器 """ 迭代器: 能被next方法调用,并且不断返回下一个值的对象,是迭代器(对象) 特征:迭代器会生成惰性序列,它通过计算 ...
-
五、ibatis中#和$的区别和使用
1.#和$两者含义不同#:会进行预编译,而且进行类型匹配:$:不进行数据类型匹配.示例:变量name的类型是string, 值是"张三" $name$ = 张三 #na ...
-
Linux CentOS7 VMware 特殊权限set_uid、特殊权限set_gid、特殊权限stick_bit、软链接文件、硬连接文件
一.特殊权限set_uid root用户本身拥有对/etc/passwd的写权限,无可厚非:那普通用户呢,这里就用到了setuid,setuid的作用是“让执行该命令的用户以该命令拥有者的权限去执行” ...
-
threading 多线程
# coding:utf- import time from threading import Thread def foo(x):#这里可以带参数def foo(x) print "foo ...
-
C++ 标准模板库STL 队列 queue 使用方法与应用介绍
C++ 标准模板库STL 队列 queue 使用方法与应用介绍 queue queue模板类的定义在<queue>头文件中. 与stack模板类很相似,queue模板类也需要两个模板参数, ...
-
CSS-lineheight
.test div{width:300px;margin:15px 0;border:1px solid #000;}.test p{margin:0;font-size:30px;}.fixed d ...
-
greenplum 存储过程 变量类型
参考: https://www.cnblogs.com/kungfupanda/p/4478917.html
-
Centos7下 Oracle11G自动备份
1.创建备份目录: [root@Centos ~]# mkdir -p /home/oracle/backup 2.设置目录权限: [root@Centos ~]# chown -R oracle:o ...
Python函数04/生成器/推导式/内置函数 目录 Python函数04/生成器/推导式/内置函数 内容大纲 1.生成器 2.推导式 3.内置函数(一) 4.今日总结 5.今日练习 内容大纲 1.生 ...
源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...
迭代器 任何一个类,只要其实现了__iter__方法,就算是一个可迭代对象.可迭代对象的__iter__方法返回的对象是迭代器,迭代器类需要实现next方法.一般来说,实现了__iter__方法的类肯 ...
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...
可迭代对象:obj.__iter__ 迭代器:iter1=obj.__iter() 1iter1.__next__ 2iter2.__next__ 迭代器: 优点:不依赖索引 ...
首先看一下什么是列表生成式 >>> [i*2 for i in range(10)] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] >>> ...
迭代器 迭代器对象:有__next__()方法的对象是迭代器对象,迭代器对象依赖__next__()方法进行依次取值 with open('text.txt','rb',) as f: res = f ...
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
-
【剑指Offer面试编程题】题目1372:最大子向量和--九度OJ
题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但 ...
-
storm的JavaAPI运行报错
报错:java.lang.NoClassDefFoundError: org/apache/storm/topology/IRichSpout 原因:idea的bug:本地运行时设置scope为pro ...
-
day11-Python运维开发基础(迭代器与可迭代对象、高阶函数)
1. 迭代器与可迭代对象 # ### 迭代器 """ 迭代器: 能被next方法调用,并且不断返回下一个值的对象,是迭代器(对象) 特征:迭代器会生成惰性序列,它通过计算 ...
-
五、ibatis中#和$的区别和使用
1.#和$两者含义不同#:会进行预编译,而且进行类型匹配:$:不进行数据类型匹配.示例:变量name的类型是string, 值是"张三" $name$ = 张三 #na ...
-
Linux CentOS7 VMware 特殊权限set_uid、特殊权限set_gid、特殊权限stick_bit、软链接文件、硬连接文件
一.特殊权限set_uid root用户本身拥有对/etc/passwd的写权限,无可厚非:那普通用户呢,这里就用到了setuid,setuid的作用是“让执行该命令的用户以该命令拥有者的权限去执行” ...
-
threading 多线程
# coding:utf- import time from threading import Thread def foo(x):#这里可以带参数def foo(x) print "foo ...
-
C++ 标准模板库STL 队列 queue 使用方法与应用介绍
C++ 标准模板库STL 队列 queue 使用方法与应用介绍 queue queue模板类的定义在<queue>头文件中. 与stack模板类很相似,queue模板类也需要两个模板参数, ...
-
CSS-lineheight
.test div{width:300px;margin:15px 0;border:1px solid #000;}.test p{margin:0;font-size:30px;}.fixed d ...
-
greenplum 存储过程 变量类型
参考: https://www.cnblogs.com/kungfupanda/p/4478917.html
-
Centos7下 Oracle11G自动备份
1.创建备份目录: [root@Centos ~]# mkdir -p /home/oracle/backup 2.设置目录权限: [root@Centos ~]# chown -R oracle:o ...