python之迭代器与生成器
python之迭代器与生成器
可迭代
假如现在有一个列表,有一个int类型的12345。我们循环输出。
- list=[1,2,3,4,5]
- for i in list:
- print(i)
- for i in 12345:
- print(i)
结果:
- Traceback (most recent call last):
- File "C:/Pycham/生成器与迭代器/test1.py", line 6, in <module>
- for i in 12345:
- TypeError: 'int' object is not iterable
- 1
- 2
- 3
- 4
- 5
- 报错显示:1234不是可以被迭代的。
- 那python中哪些是可迭代的:字符串、列表、元组、字典、集合。
- for循环工作机制:for循环在循环一个对象的时候,会调用这个对象的iter方法,得到迭代器,然后在调用这个迭代器的next方法,去获得这个迭代器中包涵的每个值。
现在可能我们不太明白,什么是iter方法,什么是迭代器,什么是next方法。
迭代器
- 但是如果只是将数据集内的数据“一个挨着一个的取出来,for循环就可以做到,为什么要使用迭代器呢?迭代器是什么?
- 迭代器能迭代的一定是可以迭代的数据类型。
- 如果我们要使用迭代器,一定要将可以被迭代的数据集转为迭代器,使用__iter__()。
- #列表生成式
- list=[1,2,3,4,5]
- #生成器
- gen=list.__iter__()
- print(list)
- print(gen)
- 结果:
- [1, 2, 3, 4, 5]
- <list_iterator object at 0x0000000002627278>
迭代器的三个方法
- iter_l = [1,2,3,4,5,6].__iter__()
- #获取迭代器中元素的长度
- print(iter_l.__length_hint__())
- #根据索引值指定从哪里开始迭代
- print(iter_l.__setstate__(2))
- #一个一个的取值
- print(iter_l.__next__())
- 结果:
6- None
- 3
循环输出迭代器的内容
注意:
很重要的特性,就是不可逆,只能前进,不能后退。
如果迭代的次数超过里面的数据,就会报错。
- l = [1,2,3,4]
- l_iter = l.__iter__()
- while True:
- try:
- item = l_iter.__next__()
- print(item)
- except StopIteration:
- break
- 总结:一个对象是否可迭代,全都取决于这个对象是否有iter方法,调用对象的iter方法,就回返回一个迭代器,这个迭代器一定具有next方法,在调用这个迭代器的next方法时,迭代器就回返回它的下一个值,当迭代器中没有
- 值可以返回了,就回抛出一个名为StopIteration的异常,停止迭代。
- for循环的工作机制,可以让我们遍历任何一个可迭代的数据集。
- 虽然序列类型字符串,列表,元组都有下标,你用下标的方式访问。
- 但是非序列类型像字典,集合,文件对象这样的数据类型也是可迭代的。
生成器
- 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
- 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator
- 生成器是一个特殊的程序,可以被用作控制循环的迭代行为,python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可以使用next()函数和send()函数恢复生成器。
- 生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,但是,不同于一般的函数会一次性返回包括了所有数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减小,而且允许调用函数可以很快的处理前几个返回值,因此生成器看起来像是一个函数,但是表现得却像
是迭代器。- 总结:生成器是个比较特殊的可迭代对象,它与其他的可迭代对象不太一样的地方,其他的可迭代对象需要调用iter方法,返回个迭代器对象,然后通过迭代器对象去执行next方法,获取迭代器中的值,但是生成器直接可以被迭代,无需执行iter方法。
- 生成器Generator:
- 本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
- 特点:惰性运算,开发者自定义
初始生成器
- import time
- def genrator_fun1():
- a = 1
- print('现在定义了a变量')
- yield a
- b = 2
- print('现在又定义了b变量')
- yield b
- g1 = genrator_fun1()
- print('g1 : ',g1) #打印g1可以发现g1就是一个生成器
- print('-'*20) #我是华丽的分割线
- print(next(g1))
- time.sleep(1) #sleep一秒看清执行过程
- print(next(g1))
python中生成器有两种表达形式
- 函数式生成器:在常规的函数中定义的生成器,语句的返回值不再使用return去返回,而是使用yield关键字每次返回一个结果,一个函数中不可以有多个return,但是可以有多个yield,函数中的每一个yield都会返回一个结果,每执行一个yield,函数的执行状态都会被‘挂起’可以理解
为暂停,下次继续调用这个函数的时候,会从上次挂起的位置继续向下执行。
- def func1():
- yield 1
- print("第一个yield执行完成~")
- yield 2
- print("第二个yield执行完成~")
- yield 3
- print("第三个yield执行完成~")
- for i in func1():
- print(i)
- 结果:
1- 第一个yield执行完成~
- 2
- 第二个yield执行完成~
- 3
- 第三个yield执行完成~
- 生成器表达式:使用类似于列表推导式的方法,但是返回的对象不再是一个列表,而是一个可以按需生成结果的一个对象(生成器)。
- 只要把一个列表生成式的[]中括号改为()小括号,就创建一个generator
- #列表生成式
- lis = [x*x for x in range(10)]
- print(lis)
- #生成器
- generator_ex = (x*x for x in range(10))
- print(generator_ex)
- 结果:
- [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
- <generator object <genexpr> at 0x000002A4CBF9EBA0>
for循环输出生成器的值
- #生成器
- generator_ex = (x*x for x in range(10))
- for i in generator_ex:
- print(i)
- 结果:
- 0
- 1
- 4
- 9
- 16
- 25
- 36
- 49
- 64
- 81
- 所以我们创建一个generator后,基本上永远不会调用next(),而是通过for循环来迭代,并且不需要关心StopIteration的错误(迭代超过长度)。
- 使用生成器的优点:
- 延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
最后示例:
- import time
- def cumtom(name):
- print('%s准备吃包子' %name)
- time.sleep(1)
- while 1:
- count=yield
- print('%s吃到第%d个包子' %(name,count))
- def producter():
- con1.__next__()
- con2.__next__()
- n=1
- while 1:
- time.sleep(1)
- print('已经生产出来%d、%d个包子' %(n,n+1))
- #通过send方法通知
- con1.send(n)
- con2.send(n+1)
- n+=2
- con1=cumtom('cumtom1')
- con2=cumtom('cumtom2')
- producter()
- cumtom1准备吃包子
- cumtom2准备吃包子
- 已经生产出来1、2个包子
- cumtom1吃到第1个包子
- cumtom2吃到第2个包子
- 已经生产出来3、4个包子
- cumtom1吃到第3个包子
- cumtom2吃到第4个包子
- 已经生产出来5、6个包子
- cumtom1吃到第5个包子
- cumtom2吃到第6个包子
- 已经生产出来7、8个包子
- cumtom1吃到第7个包子
- cumtom2吃到第8个包子
- 已经生产出来9、10个包子
- cumtom1吃到第9个包子
- cumtom2吃到第10个包子
- 已经生产出来11、12个包子
- cumtom1吃到第11个包子
- cumtom2吃到第12个包子
- 已经生产出来13、14个包子
- cumtom1吃到第13个包子
- cumtom2吃到第14个包子
- 已经生产出来15、16个包子
- cumtom1吃到第15个包子
- cumtom2吃到第16个包子
python之迭代器与生成器的更多相关文章
- python基础—迭代器、生成器
python基础-迭代器.生成器 1 迭代器定义 迭代的意思是重复做一些事很多次,就像在循环中做的那样. 只要该对象可以实现__iter__方法,就可以进行迭代. 迭代对象调用__iter__方法会返 ...
- Python之迭代器和生成器
Python 迭代器和生成器 迭代器 Python中的迭代器为类序列对象(sequence-like objects)提供了一个类序列的接口,迭代器不仅可以对序列对象(string.list.tupl ...
- 【Python】迭代器、生成器、yield单线程异步并发实现详解
转自http://blog.itpub.net/29018063/viewspace-2079767 大家在学习python开发时可能经常对迭代器.生成器.yield关键字用法有所疑惑,在这篇文章将从 ...
- python的迭代器、生成器、装饰器
迭代器.生成器.装饰器 在这个实验里我们学习迭代器.生成器.装饰器有关知识. 知识点 迭代器 生成器 生成器表达式 闭包 装饰器 实验步骤 1. 迭代器 Python 迭代器(Iterators)对象 ...
- Python之迭代器,生成器
迭代器 1.什么是可迭代对象 字符串.列表.元组.字典.集合都可以被for循环,说明他们都是可迭代的. from collections import Iterable l = [1,2,3,4] t ...
- python之迭代器、生成器与面向过程编程
目录 一 迭代器 二 生成器 三 面向过程编程 一.迭代器 1.迭代器的概念理解 ''' 迭代器从字面上理解就是迭代的工具.而迭代是每次的开始都是基于上一次的结果,不是周而复始的,而是不断发展的. ' ...
- day13 python学习 迭代器,生成器
1.可迭代:当我们打印 print(dir([1,2])) 在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...
- Python之迭代器及生成器
一. 迭代器 1.1 什么是可迭代对象 字符串.列表.元组.字典.集合 都可以被for循环,说明他们都是可迭代的. 我们怎么来证明这一点呢? from collections import Itera ...
- python基础----迭代器、生成器、协程函数及应用(面向过程实例)
一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代 ...
随机推荐
- HttpListener通讯成功案例
1.创建WindowsService,如下代码 using System;using System.Net;using System.Net.Sockets;using System.ServiceP ...
- restricted 模式及其 使用
什么是数据库的RESTRICTED 模式 注:以下内容来至:百度知道 --数据库受限模式,在这个模式下只有RESTRICTED SESSION 权限的人才可以登陆,一般用与数据库维护的时候使用. RE ...
- Swift中使用oc代码桥接设置
1 将oc的代码拖入项目中 2 新建一个头文件 在头文件中导入你想用的oc头文件 import "****.h" 3 在设置build Setting 中搜索bird 找到 Ob ...
- python面试1-30题
1.一行代码实现1--100之和 利用sum()函数求和 2.如何在一个函数内部修改全局变量 利用global 修改全局变量 3.列出5个python标准库 os:提供了不少与操作系统相关联的函数 s ...
- mysql视图的作用
测试表:user有id,name,age,sex字段 测试表:goods有id,name,price字段 测试表:ug有id,userid,goodsid字段 视图的作用实在是太强大了,以下是我体验过 ...
- Feign服务消费者
Feign的优点:面向接口,完全不用管实现,传入规定格式的数据就可以了 搭建消费者项目(FeignDemo) 1.创建pom.xml <project xmlns="http://ma ...
- MySQL数据库驱动jar包
地址:https://www.mysql.com/
- Python基础之封装
一.什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其 含义是其他程序无法调用. 要了解封装,离不开“私有化”,就是将类或者 ...
- MySQL----数据库练习
一.多对多的正反向查询 class Class(models.Model): name = models.CharField(max_length=32,verbose_name="班级名& ...
- 插件使用一表单验证一validation
jquery-validation是一款前端经验js插件,可以验证必填字段.邮件.URL.数字范围等,在表单中应用非常广泛. 官方网站 https://jqueryvalidation.org/ 源码 ...