python之迭代器与生成器

可迭代

假如现在有一个列表,有一个int类型的12345。我们循环输出。

  1. list=[1,2,3,4,5]
  2. for i in list:
  3. print(i)
  4. for i in 12345:
  5. print(i)

结果:

  1. Traceback (most recent call last):
  2. File "C:/Pycham/生成器与迭代器/test1.py", line 6, in <module>
  3. for i in 12345:
  4. TypeError: 'int' object is not iterable
  5. 1
  6. 2
  7. 3
  8. 4
  9. 5
  1. 报错显示:1234不是可以被迭代的。
  2.  
  3. python中哪些是可迭代的:字符串、列表、元组、字典、集合。
  1. for循环工作机制:for循环在循环一个对象的时候,会调用这个对象的iter方法,得到迭代器,然后在调用这个迭代器的next方法,去获得这个迭代器中包涵的每个值。
    现在可能我们不太明白,什么是iter方法,什么是迭代器,什么是next方法。

  

迭代器

  1. 但是如果只是将数据集内的数据“一个挨着一个的取出来,for循环就可以做到,为什么要使用迭代器呢?迭代器是什么?
  2. 迭代器能迭代的一定是可以迭代的数据类型。
  3. 如果我们要使用迭代器,一定要将可以被迭代的数据集转为迭代器,使用__iter__()

  

  1. #列表生成式
  2. list=[1,2,3,4,5]
  3. #生成器
  4. gen=list.__iter__()
  5. print(list)
  6. print(gen)
  7.  
  8. 结果:
  9. [1, 2, 3, 4, 5]
  10. <list_iterator object at 0x0000000002627278>

 

迭代器的三个方法

  1. iter_l = [1,2,3,4,5,6].__iter__()
  2. #获取迭代器中元素的长度
  3. print(iter_l.__length_hint__())
  4. #根据索引值指定从哪里开始迭代
  5. print(iter_l.__setstate__(2))
  6. #一个一个的取值
  7. print(iter_l.__next__())

  

  1. 结果:
    6
  2. None
  3. 3

循环输出迭代器的内容

注意:

很重要的特性,就是不可逆,只能前进,不能后退。

如果迭代的次数超过里面的数据,就会报错。

  1. l = [1,2,3,4]
  2. l_iter = l.__iter__()
  3. while True:
  4. try:
  5. item = l_iter.__next__()
  6. print(item)
  7. except StopIteration:
  8. break

  

  1. 总结:一个对象是否可迭代,全都取决于这个对象是否有iter方法,调用对象的iter方法,就回返回一个迭代器,这个迭代器一定具有next方法,在调用这个迭代器的next方法时,迭代器就回返回它的下一个值,当迭代器中没有
  2. 值可以返回了,就回抛出一个名为StopIteration的异常,停止迭代。
  3. for循环的工作机制,可以让我们遍历任何一个可迭代的数据集。
  4. 虽然序列类型字符串,列表,元组都有下标,你用下标的方式访问。
  5. 但是非序列类型像字典,集合,文件对象这样的数据类型也是可迭代的。

  

生成器

  1. 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
  2.  
  3. 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator
  4.  
  5. 生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
  6.  
  7. 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像
    是迭代器。
  8.  
  9. 总结:生成器是个比较特殊的可迭代对象,它与其他的可迭代对象不太一样的地方,其他的可迭代对象需要调用iter方法,返回个迭代器对象,然后通过迭代器对象去执行next方法,获取迭代器中的值,但是生成器直接可以被迭代,无需执行iter方法。

  

  1.   
  2. 生成器Generator
  3.  
  4.   本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
  5.  
  6.   特点:惰性运算,开发者自定义

  

初始生成器

  1. import time
  2. def genrator_fun1():
  3. a = 1
  4. print('现在定义了a变量')
  5. yield a
  6. b = 2
  7. print('现在又定义了b变量')
  8. yield b
  9.  
  10. g1 = genrator_fun1()
  11. print('g1 : ',g1) #打印g1可以发现g1就是一个生成器
  12. print('-'*20) #我是华丽的分割线
  13. print(next(g1))
  14. time.sleep(1) #sleep一秒看清执行过程
  15. print(next(g1))

python中生成器有两种表达形式

  1. 函数式生成器:在常规的函数中定义的生成器,语句的返回值不再使用return去返回,而是使用yield关键字每次返回一个结果,一个函数中不可以有多个return,但是可以有多个yield,函数中的每一个yield都会返回一个结果,每执行一个yield,函数的执行状态都会被‘挂起’可以理解
    为暂停,下次继续调用这个函数的时候,会从上次挂起的位置继续向下执行。
  1. def func1():
  2.  
  3. yield 1
  4.  
  5. print("第一个yield执行完成~")
  6.  
  7. yield 2
  8.  
  9. print("第二个yield执行完成~")
  10.  
  11. yield 3
  12.  
  13. print("第三个yield执行完成~")
  14.  
  15. for i in func1():
  16. print(i)

  

  1. 结果:
    1
  2. 第一个yield执行完成~
  3. 2
  4. 第二个yield执行完成~
  5. 3
  6. 第三个yield执行完成~

  

  1. 生成器表达式:使用类似于列表推导式的方法,但是返回的对象不再是一个列表,而是一个可以按需生成结果的一个对象(生成器)。
  2. 只要把一个列表生成式的[]中括号改为()小括号,就创建一个generator
  1. #列表生成式
  2. lis = [x*x for x in range(10)]
  3. print(lis)
  4. #生成器
  5. generator_ex = (x*x for x in range(10))
  6. print(generator_ex)
  7.  
  8. 结果:
  9. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  10. <generator object <genexpr> at 0x000002A4CBF9EBA0>

  

for循环输出生成器的值

  1. #生成器
  2. generator_ex = (x*x for x in range(10))
  3. for i in generator_ex:
  4. print(i)
  5.  
  6. 结果:
  7. 0
  8. 1
  9. 4
  10. 9
  11. 16
  12. 25
  13. 36
  14. 49
  15. 64
  16. 81
  1. 所以我们创建一个generator后,基本上永远不会调用next(),而是通过for循环来迭代,并且不需要关心StopIteration的错误(迭代超过长度)。
  1. 使用生成器的优点:
  2.  
  3. 延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

  

最后示例:

  1. import time
  2.  
  3. def cumtom(name):
  4. print('%s准备吃包子' %name)
  5. time.sleep(1)
  6. while 1:
  7. count=yield
  8. print('%s吃到第%d个包子' %(name,count))
  9.  
  10. def producter():
  11. con1.__next__()
  12. con2.__next__()
  13. n=1
  14. while 1:
  15. time.sleep(1)
  16. print('已经生产出来%d、%d个包子' %(n,n+1))
  17. #通过send方法通知
  18. con1.send(n)
  19. con2.send(n+1)
  20. n+=2
  21.  
  22. con1=cumtom('cumtom1')
  23. con2=cumtom('cumtom2')
  24. producter()

  

  1. cumtom1准备吃包子
  2. cumtom2准备吃包子
  3. 已经生产出来12个包子
  4. cumtom1吃到第1个包子
  5. cumtom2吃到第2个包子
  6. 已经生产出来34个包子
  7. cumtom1吃到第3个包子
  8. cumtom2吃到第4个包子
  9. 已经生产出来56个包子
  10. cumtom1吃到第5个包子
  11. cumtom2吃到第6个包子
  12. 已经生产出来78个包子
  13. cumtom1吃到第7个包子
  14. cumtom2吃到第8个包子
  15. 已经生产出来910个包子
  16. cumtom1吃到第9个包子
  17. cumtom2吃到第10个包子
  18. 已经生产出来1112个包子
  19. cumtom1吃到第11个包子
  20. cumtom2吃到第12个包子
  21. 已经生产出来1314个包子
  22. cumtom1吃到第13个包子
  23. cumtom2吃到第14个包子
  24. 已经生产出来1516个包子
  25. cumtom1吃到第15个包子
  26. cumtom2吃到第16个包子

  

python之迭代器与生成器的更多相关文章

  1. python基础—迭代器、生成器

    python基础-迭代器.生成器 1 迭代器定义 迭代的意思是重复做一些事很多次,就像在循环中做的那样. 只要该对象可以实现__iter__方法,就可以进行迭代. 迭代对象调用__iter__方法会返 ...

  2. Python之迭代器和生成器

    Python 迭代器和生成器 迭代器 Python中的迭代器为类序列对象(sequence-like objects)提供了一个类序列的接口,迭代器不仅可以对序列对象(string.list.tupl ...

  3. 【Python】迭代器、生成器、yield单线程异步并发实现详解

    转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...

  4. python的迭代器、生成器、装饰器

    迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...

  5. Python之迭代器,生成器

    迭代器 1.什么是可迭代对象 字符串.列表.元组.字典.集合都可以被for循环,说明他们都是可迭代的. from collections import Iterable l = [1,2,3,4] t ...

  6. python之迭代器、生成器与面向过程编程

    目录 一 迭代器 二 生成器 三 面向过程编程 一.迭代器 1.迭代器的概念理解 ''' 迭代器从字面上理解就是迭代的工具.而迭代是每次的开始都是基于上一次的结果,不是周而复始的,而是不断发展的. ' ...

  7. day13 python学习 迭代器,生成器

    1.可迭代:当我们打印 print(dir([1,2]))   在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...

  8. Python之迭代器及生成器

    一. 迭代器 1.1 什么是可迭代对象 字符串.列表.元组.字典.集合 都可以被for循环,说明他们都是可迭代的. 我们怎么来证明这一点呢? from collections import Itera ...

  9. python基础----迭代器、生成器、协程函数及应用(面向过程实例)

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

随机推荐

  1. HttpListener通讯成功案例

    1.创建WindowsService,如下代码 using System;using System.Net;using System.Net.Sockets;using System.ServiceP ...

  2. restricted 模式及其 使用

    什么是数据库的RESTRICTED 模式 注:以下内容来至:百度知道 --数据库受限模式,在这个模式下只有RESTRICTED SESSION 权限的人才可以登陆,一般用与数据库维护的时候使用. RE ...

  3. Swift中使用oc代码桥接设置

    1 将oc的代码拖入项目中 2 新建一个头文件 在头文件中导入你想用的oc头文件  import "****.h" 3 在设置build Setting 中搜索bird 找到 Ob ...

  4. python面试1-30题

    1.一行代码实现1--100之和 利用sum()函数求和 2.如何在一个函数内部修改全局变量 利用global 修改全局变量 3.列出5个python标准库 os:提供了不少与操作系统相关联的函数 s ...

  5. mysql视图的作用

    测试表:user有id,name,age,sex字段 测试表:goods有id,name,price字段 测试表:ug有id,userid,goodsid字段 视图的作用实在是太强大了,以下是我体验过 ...

  6. Feign服务消费者

    Feign的优点:面向接口,完全不用管实现,传入规定格式的数据就可以了 搭建消费者项目(FeignDemo) 1.创建pom.xml <project xmlns="http://ma ...

  7. MySQL数据库驱动jar包

    地址:https://www.mysql.com/

  8. Python基础之封装

    一.什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其 含义是其他程序无法调用. 要了解封装,离不开“私有化”,就是将类或者 ...

  9. MySQL----数据库练习

    一.多对多的正反向查询 class Class(models.Model): name = models.CharField(max_length=32,verbose_name="班级名& ...

  10. 插件使用一表单验证一validation

    jquery-validation是一款前端经验js插件,可以验证必填字段.邮件.URL.数字范围等,在表单中应用非常广泛. 官方网站 https://jqueryvalidation.org/ 源码 ...