【Python3之迭代器,生成器】
一、可迭代对象和迭代器
1.迭代的概念
上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
注:循环不是迭代
while True: #只满足重复,因而不是迭代
print('====>')
2.可迭代的对象
内置__iter__方法的,都是可迭代的对象。
list是可迭代对象,dict是可迭代对象,set也是可迭代对象。
[1,2].__iter__()
'hello'.__iter__()
(1,2).__iter__() {'a':1,'b':2}.__iter__()
{1,2,3}.__iter__()
例如:

x = [1, 2, 3]
y = iter(x)
z = iter(x)
print(next(y))
print(next(y))
print(next(z))
print(type(x))
print(type(y))

输出
1
2
1
<class 'list'>
<class 'list_iterator'>
如下图所示
这里x是一个可迭代对象,y和z是两个独立的迭代器,迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。
迭代器有一种具体的迭代器类型,比如list_iterator,set_iterator。可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
3.迭代器
- 1.为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。
- 2.迭代器定义:
迭代器:可迭代对象执行__iter__方法,得到的结果就是迭代器,迭代器对象有__next__方法
它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常
- 3.迭代器的实现
例:

i=[1,2,3].__iter__() print(i) #迭代器 print(i.__next__())
print(i.__next__())
print(i.__next__())
#print(i.__next__()) #抛出异常:StopIteration

输出
<list_iterator object at 0x1019c3eb8>
1
2
3
每次调用next()方法的时候做两件事:
- 为下一次调用
next()方法修改状态 - 为当前这次调用生成返回结果
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
- 4.如何判断迭代器对象和可迭代对象

from collections import Iterable,Iterator
'abc'.__iter__()
().__iter__()
[].__iter__()
{'a':1}.__iter__()
{1,2}.__iter__() f=open('a.txt','w')
f.__iter__()
#判断是否为可迭代对象,以下都是
print(isinstance('abc',Iterable))
print(isinstance([],Iterable))
print(isinstance((),Iterable))
print(isinstance({'a':1},Iterable))
print(isinstance({1,2},Iterable))
print(isinstance(f,Iterable))
#判断是否为迭代器,只有文件是
print(isinstance('abc',Iterator))
print(isinstance([],Iterator))
print(isinstance((),Iterator))
print(isinstance({'a':1},Iterator))
print(isinstance({1,2},Iterator))
print(isinstance(f,Iterator))

输出

True
True
True
True
True
True
False
False
False
False
False
True

可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象
迭代器:有__iter__和__next__()方法
注:对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身
- 5.迭代器的优点和缺点
优点:
1.提供了一种不依赖下标的迭代方式
2.就跌迭代器本身来说,更节省内存
缺点:
1. 无法获取迭代器对象的长度
2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退
二、生成器
1.定义
生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现__next__()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。
也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。
yield的功能:
1.相当于为函数封装好__iter__和__next__
2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
例:

def counter(n):
print('start...')
i=0
while i < n:
yield i
i+=1
print('end...') g=counter(5)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# print(next(g)) #会报错

输出
start...
0
1
2
3
4
2.生成器函数
- 生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行;
普通函数return返回

def lay_eggs(num):
egg_list=[]
for egg in range(num):
egg_list.append('蛋%s' %egg)
return egg_list yikuangdan=lay_eggs(10) #我们拿到的是蛋
print(yikuangdan)

输出
['蛋0', '蛋1', '蛋2', '蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']
迭代器函数

def lay_eggs(num):
for egg in range(num):
res='蛋%s' %egg
yield res #生成器关键语法
print('下完一个蛋') laomuji=lay_eggs(10) #我们拿到的是一只母鸡
print(laomuji)
print(laomuji.__next__()) #迭代 蛋0
print(laomuji.__next__()) #蛋1
print(laomuji.__next__()) #蛋2
egg_l=list(laomuji)
print(egg_l)

输出

蛋0
下完一个蛋
蛋1
下完一个蛋
蛋2
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
下完一个蛋
['蛋3', '蛋4', '蛋5', '蛋6', '蛋7', '蛋8', '蛋9']

3.生成器表达式
- 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表;
food=yield food_list
#g.send('food1'),先把food1传给yield,由yield赋值给food,然后返回给food_list,然后再往下执行,直到再次碰到yield,然后把yield后的返回值返回给food_list
例
注意:开始生成器不能send非空值

def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food)) g=eater('hexin')
print(g) #生成器
print(g.send('food1')) #传值

输出
Traceback (most recent call last):
<generator object eater at 0x1049030f8> #生成器对象
File "/Users/hexin/PycharmProjects/py3/day5/2.py", line 71, in <module>
print(g.send('food1'))
TypeError: can't send non-None value to a just-started generator #开始生成器不能send非空值
- 初始化后

def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food)) g=eater('hexin')
print(g) #生成器
next(g) #等同于 g.send(None),初始化 print(g.send('food1'))

输出
<generator object eater at 0x107cde258>
hexin ready to eat
hexin start to eat food1
['food1']
- 为了防止忘记初始化,可利用装饰器进行初始化,如下

def deco(func): #初始化函数
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
next(res) #等同于 g.send(None),初始化
return res
return wrapper @deco #用初始化函数装饰器,调用初始化函数
def eater(name): #协程函数
print('%s ready to eat' %name)
food_list=[]
while True:
food=yield food_list #装饰器表达式
food_list.append(food)
print('%s start to eat %s' %(name,food)) g=eater('hexin')
# print(g) #生成器
# next(g) #等同于 g.send(None),初始化 print(g.send('food1'))
print(g.send('food2'))
print(g.send('food3'))

输出

hexin ready to eat
hexin start to eat food1
['food1']
hexin start to eat food2
['food1', 'food2']
hexin start to eat food3
['food1', 'food2', 'food3']

【Python3之迭代器,生成器】的更多相关文章
- python3之迭代器&生成器
1.迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式.. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不 ...
- 4.10 Python3 进阶 - 迭代器 & 生成器
>>返回主目录 源码 from typing import Iterable, Iterator # 可迭代对象:字符串.列表.元组.字典.集合.range().enumerate()等 ...
- python3.7 迭代器和生成器
#!/usr/bin/env python __author__ = "lrtao2010" #python3.7 迭代器和生成器 #迭代器协议: ''' 1.迭代器协议是指:对象 ...
- python3.5-day5_迭代器_生成器_装饰器_模块
笔者QQ 360212316 迭代器&生成器 生成器: 一个函数调用返回一个迭代器,那这个函数叫做生成器,如果函数中包含yield语法,那么这个函数就会变成生成器 生成器的特点: 1.生成器必 ...
- day04 装饰器 迭代器&生成器 Json & pickle 数据序列化 内置函数
回顾下上次的内容 转码过程: 先decode 为 Unicode(万国码 ) 然后encode 成需要的格式 3.0 默认是Unicode 不是UTF-8 所以不需要指定 如果非要转为U ...
- Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
- Python(四)装饰器、迭代器&生成器、re正则表达式、字符串格式化
本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解 ...
- Python 迭代器&生成器
1.内置参数 Built-in Functions abs() dict() help() min() setattr() all() dir() hex() next() slice ...
- python杂记-4(迭代器&生成器)
#!/usr/bin/env python# -*- coding: utf-8 -*-#1.迭代器&生成器#生成器#正确的方法是使用for循环,因为generator也是可迭代对象:g = ...
- Python学习笔记——基础篇【第四周】——迭代器&生成器、装饰器、递归、算法、正则表达式
目录 1.迭代器&生成器 2.装饰器 a.基本装饰器 b.多参数装饰器 3.递归 4.算法基础:二分查找.二维数组转换 5.正则表达式 6.常用模块学习 #作业:计算器开发 a.实现加减成熟及 ...
随机推荐
- CMDB运维开发项目
ITIL:Information Technology Infrastructure Library 信息技术基础架构库,主要适用于IT服务管理(ITSM).ITIL为企业的IT服务管理实践提供了一个 ...
- 总结Ajax验证注册功能的两种方式
方法一:使用jqueryForm插件提交表单注册 ①首先引入jquery和jqueryForm插件 <script type="text/javascript" src=&q ...
- Java程序员的C++回归路(一)
前言:工作后吃饭的语言是java,同时写一些python和js,在学习机器学习的时候发现有必要再熟悉一下c++,同时工作也有c++的使用需求.于是开始对照c++ primer自学,希望能够对同样是其他 ...
- 实现数组元素互换位置(乘机理解java参数传递)
Java中函数参数是按值传递的,在实现数组元素互换位置之前,我想先说一下Java函数参数传递过程.一般情况下我们会把参数分为基本数据类型和引用数据类型,然后分别来讲参数传递,因为他们的外在表现似乎是不 ...
- Zabbix实战-简易教程(5)--Proxy和Agent端(源码和yum方式)
3.3.1 zabbix proxy安装(源码方式) 1.创建目录 mkdir -p /usr/local/zabbix 2.安装必要软件 yum install -y fping(若安装不成功) 或 ...
- xss框架基础框架实现
0x00web服务器设计 (1)tornado处理请求和Application类要编写一个Tornado应用中最多的工作是定义类继承Tornado的RequestHandler类,主要用于将特定的ur ...
- 聚类之dbscan算法
简要的说明: dbscan为一个密度聚类算法,无需指定聚类个数. python的简单实例: # coding:utf-8 from sklearn.cluster import DBSCAN impo ...
- python 序列话模块 常用
什么是序列化? 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flatte ...
- A very hard Aoshu problem(dfs或者数位)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4403 A very hard Aoshu problem Time Limit: 2000/1000 ...
- jqgrid 分页 (基于ashx)
1:数据库表创建并往中插入200000条数据: 复制代码 CREATE TABLE [dbo].[T_School]( [ID] [int] IDENTITY(1,1) NOT NULL, [Scho ...