迭代器协议:

1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stopiteration异常,以终止迭代(只能往后走不能往前退)

2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义_iter_方法)

3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象

for循环机制:

for循环的本质:循环所有对象,全都是使用迭代器协议。

(字符串,列表,元组,字典,集合,文件对象)这些都不是可迭代对象,只不过在for循环时,调用了他们内部的_iter_方法,把他们变成了可迭代对象

然后for循环调用可迭代对象的_next_方法去取值,而且for循环会捕捉Stopiteration异常,以终止迭代。

s='abc'
s_i=s.__iter__()
print(s_i.__next__())
print(s_i.__next__())
print(s_i.__next__())
print(s_i.__next__())#抛StopIteration异常>>>a
>>>b
>>>c
>>>a
Traceback (most recent call last):
bFile "E:/ch/Pylearning/Learning_09.py", line 115, in <module>
cprint(s_i.__next__())
StopIteration

for循环的本质:

l=[1,2,3]for i in l:#i_l=l.__iter__()  i_l.__next__()print(i)

#while循环完成for循环工作
s='qwer'
i=0
while i<len(s):print(s[i])i+=1

但while循环不能遍历字典、集合、文件。
能被for循环遍历的对象都有__iter__()方法。

f=open('a.txt','r+',encoding='utf-8')
iter_f=f.__iter__()
print(iter_f.__next__(),end='')
print(iter_f.__next__(),end='')
print(iter_f.__next__(),end='')
print(iter_f.__next__(),end='')

for循环就是基于迭代器协议提供了一个统一的可以遍历所有对象的方法,在遍历之前,先调用对象的__iter__方法将起转换成一个迭代器,然后使用迭代器协议去实现循环访问,这样所有的对象就都可以通过for循环来遍历了。

用while循环模拟for循环机制:

dic={'a':1,'b':2,'c':3}
iter_d=dic.__iter__()
while True:try:print(iter_d.__next__())except StopIteration:print('迭代完成')break>>>a
b
c
迭代完成

next()方法是系统自带方法,本质上也是调用__next__()方法

l=[1,2,3]
a=l.__iter__()
print(next(a))#next()————》调用a.__next__()方法

只要遵循迭代器协议,那么该对象就是可迭代对象

生成器:

生成器:可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__()方法),所以生成器就是可迭代对象

生成器分类及在python中的表现形式:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结构。yield语句一次返回一个结果,每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行.yield相当于return,但是可以在一个函数中使用多次。yield相当于封装了__iter__()方法,直接得到生成器对象。

def test():yield 1yield 2yield 3yield 4g=test()
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())>>>1
2
3
4

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

三元表达式

#三元表达式
name='ss'
#如果name='alex'返回'sb'否则返回'hand'
r='sb' if name=='alex' else 'hand'
print(r)

列表解析:

#将列表中放入10个鸡蛋
l1=[]
for i in range(1,11):l1.append('鸡蛋%s'%i)
print(l1)>>>['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9', '鸡蛋10']#列表解析的方式
l2=['鸡蛋%s'%i for i in range(1,11)]
print(l2)>>>['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9', '鸡蛋10']

l3=['鸡蛋%s'%i for i in range(1,11) if i<5]#没有四元表达式
print(l3)>>>['鸡蛋1', '鸡蛋2', '鸡蛋3', '鸡蛋4']

生成器表达式:

1.把列表解析的[]换成()得到的就是生成器表达式

2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

l2=['鸡蛋%s'%i for i in range(1,11)]
#生成器:
l4=('鸡蛋%s'%i for i in range(1,11))
print(l4)
print(l4.__next__())
print(l4.__next__())
print(next(l4))
print(next(l4))>>><generator object <genexpr> at 0x000001FFD4A3C1A8>
鸡蛋1
鸡蛋2
鸡蛋3
鸡蛋4

3.pyhton不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如:sum函数是python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

l=[1,2,3,4,5,6,7,8,9,7,4,6,4,1]print(sum([1,2,3,4,5,6]))
print(sum(i for i in range(0,1000000)))#生成器表达式方式

yield:

使用第一次__next__()则表示函数运行到第一个yield,使用第二次__next__()则表示函数从第一个yield运行到第二个yield,以此类推。。。

import timedef test():print('开始生孩子了')yield '我'time.sleep(3)print('又开始生孩子了')yield '我的孩子'time.sleep(3)print('又又开始生孩子了')yield '我的孩子的孩子'res=test()print(res.__next__())
print(res.__next__())
print(res.__next__())>>>开始生孩子了
我
>>>又开始生孩子了
我的孩子
>>>又又开始生孩子了
我的孩子的孩子

生成器函数:

例1:

def product_baozi():for i in range(1,100):print('生产包子中')yield '包子%s'%iprint('卖包子')p=product_baozi()
baozi1=p.__next__()
print(baozi1)
baozi2=p.__next__()
print(baozi2)>>>生产包子中
包子1
卖包子

例2:

def product_egg():for i in range(1,1000):yield '第%s个鸡蛋'%ip=product_egg()
print(p.__next__())
print(p.__next__())
print(p.__next__())
print(p.__next__())
print(p.__next__())
print(p.__next__())
print(p.__next__())
print(p.__next__())>>>第1个鸡蛋
第2个鸡蛋
第3个鸡蛋
第4个鸡蛋
第5个鸡蛋
第6个鸡蛋
第7个鸡蛋
第8个鸡蛋

for循环遍历生成器:

def product_egg():for i in range(1,1000):yield '第%s个鸡蛋'%i p=product_egg() for i in product_egg(): print(i)

生成器总结:

def get_populartion():with open('xxx','r',encoding='utf-8') as f:for i in f :yield ip=get_populartion()
print('全国总人口约为%d'%sum(eval(i)['人口'] for i in p ))

def test():for i in range(0,4):yield it=test()
# for i in t:
#     print(i)
t1=(i for i in t)
t2=(i for i in t1)
print(list(t1))
print(list(t2))>>>[0, 1, 2, 3]
>>>[]


补充:send()用法,send与next和__next__()都可以使生成器往下执行yield 2相当于return,控制的是函数的返回值x=yield的另外一个特性,接收send传过来的值,赋值给x
# send()用法,send与next和__next__()都可以使生成器往下执行
# yield 2相当于return,控制的是函数的返回值
# x=yield的另外一个特性,接收send传过来的值,赋值给x
def test():print('开始第一次')first=yield 1print('开始第二次',first)yield 2print('开始第三次')yield 3t=test()
print(t.__next__())t1=t.send('啊啊啊啊')
print(t1)>>>开始第一次
1
开始第二次 啊啊啊啊
2

生产者消费者模型:

#两个函数并行:
#生产者消费者模型
def consumer(name):print('%s准备吃包子了'%(name))time.sleep(0.5)while True:g=yieldprint('%s开始吃%s包子了'%(name,g))def  producer():p1=consumer('alex')p1.__next__()for i in range(1,10):time.sleep(0.5)p1.send('第%d'%i)producer()>>>alex准备吃包子了
alex开始吃第1包子了
alex开始吃第2包子了
alex开始吃第3包子了
alex开始吃第4包子了
alex开始吃第5包子了
alex开始吃第6包子了
alex开始吃第7包子了
alex开始吃第8包子了
alex开始吃第9包子了

转载于:https://www.cnblogs.com/Manuel/p/10577466.html

python_10 迭代器和生成器相关推荐

  1. 完全理解Python迭代对象、迭代器、生成器

    本文源自RQ作者的一篇博文,原文是Iterables vs. Iterators vs. Generators,俺写的这篇文章是按照自己的理解做的参考翻译,算不上是原文的中译版本,推荐阅读原文,谢谢网 ...

  2. Python学习笔记3 流程控制、迭代器、生成器

    第3章 流程控制.迭代器.生成器 3.1 选择语句 1.语法:(1)if -else (2)if-elif-else 2.注意:(1)每个条件后面要使用冒号:(2)使用缩进划分语句块(3)python ...

  3. pythonfor循环遍历list_为什么for循环可以遍历list:Python中迭代器与生成器

    1 引言 只要你学了Python语言,就不会不知道for循环,也肯定用for循环来遍历一个列表(list),那为什么for循环可以遍历list,而不能遍历int类型对象呢?怎么让一个自定义的对象可遍历 ...

  4. javascript迭代器_JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释...

    javascript迭代器 by rajaraodv 通过rajaraodv JavaScript符号,迭代器,生成器,异步/等待和异步迭代器-全部简单解释 (JavaScript Symbols, ...

  5. 完全理解 Python 迭代对象、迭代器、生成器(转)

    完全理解 Python 迭代对象.迭代器.生成器 本文源自RQ作者的一篇博文,原文是Iterables vs. Iterators vs. Generators » nvie.com,俺写的这篇文章是 ...

  6. 简单介绍python迭代器和生成器

    这篇文章主要介绍了Python中的迭代器和生成器,涉及到Python中很多重要的特性,需要的朋友可以参考下,希望能够给你带来帮助 python迭代器和生成器 1.迭代器 这里用字典示例 while T ...

  7. python迭代器和生成器_python中迭代器和生成器。

    前言:很多python教程中,对python的解释不容易理解,本文记录自己的理解和体会,是对迭代器和生成器的初步理解. 迭代器: 迭代器的实质是实现了next()方法的对象,常见的元组.列表.字典都是 ...

  8. python3可迭代对象、迭代器、生成器、协程yield入门

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019-01-24 16:13:07 # @Author : cdl (1217096 ...

  9. python yield用法_Python中迭代器和生成器的区别?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

最新文章

  1. 什么是core dump linux下用core和gdb查询出现段错误的地方
  2. 2021年春季学期-信号与系统-第十一次作业参考答案-第一小题
  3. STL区间成员函数及区间算法总结
  4. 何时(不)使用Java抽象类
  5. python实战经典例子_Python基础之列表常见操作经典实例详解
  6. 配置集群Nginx+Memcached+Tomcat集群配置
  7. linux telnet 安装
  8. 知云文献翻译_研究生必备的文献翻译软件——知云文献翻译
  9. 摘抄笔记 centos内核优化
  10. 冷高轮时间windows电脑屏幕保护
  11. AtCoder Beginner Contest 240 D
  12. Java jsp导出Excel打开报格式或扩展名错误
  13. Naive Bayes Model 朴素贝叶斯 简单易懂的笔记by hch
  14. Java处理敲击键盘事件 Etch-A-Sketch玩具实现 光标画笔画图程序 Java核心技术
  15. 学生信息管理系统之 查询学籍信息流程
  16. iOS应用中crash 奔溃解析
  17. Python下载文件的方式
  18. python考试搜题神器_python实现百万英雄答题神器
  19. 第十五届东北四省大学生程序设计大赛J. Transform(计算几何,罗德里格斯旋转公式)
  20. 关于edge下载文件及codeblocks编译中文乱码问题

热门文章

  1. Palindrome DP
  2. 二分匹配和一般图匹配
  3. axure,购物车数量递增或递减
  4. 《Android进阶之光》--事件总线
  5. LNMP1.4环境中安装fileinfo插件
  6. java_eclipse_maven_svn_主题彩色插件_全屏插件
  7. ASP.NET常用语句1--20条 非常实用
  8. Java操作MySQL的中文处理方法
  9. Android基于Glide的二次封装,借鉴Glide思想二次封装Fresco
  10. RecordAccumulator分析