python可迭代对象 迭代器生成器_第八章 Python可迭代对象、迭代器和生成器-阿里云开发者社区...
8.1 可迭代对象(Iterable)
大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的。
__iter__方法会返回迭代器(iterator)本身,例如:
>>> lst = [1,2,3]
>>> lst.__iter__()
Python提供一些语句和关键字用于访问可迭代对象的元素,比如for循环、列表解析、逻辑操作符等。
判断一个对象是否是可迭代对象:
>>> from collections import Iterable # 只导入Iterable方法
>>> isinstance('abc', Iterable)
True
>>> isinstance(1, Iterable)
False
>>> isinstance([], Iterable)
True
这里的isinstance()函数用于判断对象类型,后面会讲到。
可迭代对象一般都用for循环遍历元素,也就是能用for循环的对象都可称为可迭代对象。
例如,遍历列表:
>>> lst = [1, 2, 3]
>>> for i in lst:
... print i
...
1
2
3
博客地址:http://lizhenliang.blog.51cto.com and https://yq.aliyun.com/u/lizhenliang
QQ群:323779636(Shell/Python运维开发群)
8.2 迭代器(Iterator)
具有next方法的对象都是迭代器。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。
使用迭代器的好处:
1)如果使用列表,计算值时会一次获取所有值,那么就会占用更多的内存。而迭代器则是一个接一个计算。
2)使代码更通用、更简单。
8.2.1 迭代器规则
回忆下在Python数据类型章节讲解到字典迭代器方法,来举例说明下迭代器规则:
>>> d = {'a':1, 'b':2, 'c':3}
>>> d.iteritems()
# 判断是否是迭代器
>>> from collections import Iterator
>>> isinstance(d, Iterator)
False
>>> isinstance(d.iteritems(), Iterator)
True
# 使用next方法。
>>> iter_items = d.iteritems()
>>> iter_items.next()
('a', 1)
>>> iter_items.next()
('c', 3)
>>> iter_items.next()
('b', 2)
由于字典是无序的,所以显示的是无序的,实际是按照顺序获取的下一个元素。
8.2.2 iter()函数
使用iter()函数转换成迭代器:
语法:
iter(collection) -> iterator
iter(callable, sentinel) -> iterator
>>> lst = [1, 2, 3]
>>> isinstance(lst, Iterator)
False
>>> lst.next() # 不是迭代器是不具备next()属性的
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'list' object has no attribute 'next'
>>> iter_lst = iter(lst)
>>> isinstance(iter_lst, Iterator)
True
>>> iter_lst.next()
1
>>> iter_lst.next()
2
>>> iter_lst.next()
3
8.2.3 itertools模块
itertools模块是Python内建模块,提供可操作迭代对象的函数。可以生成迭代器,也可以生成无限的序列迭代器。
有下面几种生成无限序列的方法:
count([n]) --> n, n+1, n+2, ...
cycle(p) --> p0, p1, ... plast, p0, p1, ...
repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times
也有几个操作迭代器的方法:
islice(seq, [start,] stop [, step]) --> elements from
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...
groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...
ifilter(pred, seq) --> elements of seq where pred(elem) is True
1)count生成序列迭代器
>>> from itertools import * # 导入所有方法
# 用法 count(start=0, step=1) --> count object
>>> counter = count()
>>> counter.next()
0
>>> counter.next()
1
>>> counter.next()
2
......
可以使用start参数设置开始值,step设置步长。
2)cycle用可迭代对象生成迭代器
# 用法 cycle(iterable) --> cycle object
>>> i = cycle(['a', 'b', 'c'])
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
3)repeat用对象生成迭代器
# 用法 repeat(object [,times]) -> create an iterator which returns the object,就是任意对象
>>> i = repeat(1)
>>> i.next()
1
>>> i.next()
1
>>> i.next()
1
......
可使用无限次。
也可以指定次数:
>>> i = repeat(1, 2)
>>> i.next()
1
>>> i.next()
1
>>> i.next()
Traceback (most recent call last):
File "", line 1, in
StopIteration
4)islice用可迭代对象并设置结束位置
# 用法 islice(iterable, [start,] stop [, step]) --> islice object
>>> i = islice([1,2,3],2)
>>> i.next()
1
>>> i.next()
2
>>> i.next()
Traceback (most recent call last):
File "", line 1, in
StopIteration
正常的话也可以获取的3。
5)chain用多个可迭代对象生成迭代器
# 用法 chain(*iterables) --> chain object
>>> i = chain('a','b','c')
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
6)groupby将可迭代对象中重复的元素挑出来放到一个迭代器中
# 用法 groupby(iterable[, keyfunc]) -> create an iterator which returns
>>> for key,group in groupby('abcddCca'):
... print key,list(group)
...
a ['a']
b ['b']
c ['c']
d ['d', 'd']
C ['C']
c ['c']
a ['a']
groupby方法是区分大小写的,如果想把大小写的都放到一个迭代器中,可以定义函数处理下:
>>> for key,group in groupby('abcddCca', lambda c: c.upper()):
... print key, list(group)
...
A ['a']
B ['b']
C ['c']
D ['d', 'd']
C ['C', 'c']
A ['a']
7)imap用函数处理多个可迭代对象
# 用法 imap(func, *iterables) --> imap object
>>> a = imap(lambda x, y: x * y,[1,2,3],[4,5,6])
>>> a.next()
4
>>> a.next()
10
>>> a.next()
18
8)ifilter过滤序列
# 用法 ifilter(function or None, sequence) --> ifilter object
>>> i = ifilter(lambda x: x%2==0,[1,2,3,4,5])
>>> for i in i:
... print i
...
2
4
当使用for语句遍历迭代器时,步骤大致这样的,先调用迭代器对象的__iter__方法获取迭代器对象,再调用对象的__next__()方法获取下一个元素。最后引发StopIteration异常结束循环。
8.3 生成器(Generator)
什么是生成器?
1)任何包含yield语句的函数都称为生成器。
2)生成器都是一个迭代器,但迭代器不一定是生成器。
8.3.1 生成器函数
在函数定义中使用yield语句就创建了一个生成器函数,而不是普通的函数。
当调用生成器函数时,每次执行到yield语句,生成器的状态将被冻结起来,并将结果返回__next__调用者。冻结意思是局部的状态都会被保存起来,包括局部变量绑定、指令指针。确保下一次调用时能从上一次的状态继续。
以生成斐波那契数列举例说明yield使用:
斐波那契(Fibonacci)数列是一个简单的递归数列,任意一个数都可以由前两个数相加得到。
#!/usr/bin/python
# -*- coding: utf-8 -*-
def fab(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n += 1
fab(5)
# python test.py
1
1
2
3
5
使用yied语句,只需要把print b改成yield b即可:
#!/usr/bin/python
# -*- coding: utf-8 -*-
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
# print b
a, b = b, a + b
n += 1
print fab(5)
# python test.py
可见,调用fab函数不会执行fab函数,而是直接返回了一个生成器对象,上面说过生成器就是一个迭代器。那么就可以通过next方法来返回它下一个值。
>>> import test
>>> f = test.fab(5)
>>> f.next()
1
>>> f.next()
1
>>> f.next()
2
>>> f.next()
3
>>> f.next()
5
每次fab函数的next方法,就会执行fab函数,执行到yield b时,fab函数返回一个值,下一次执行next方法时,代码从yield b的吓一跳语句继续执行,直到再遇到yield。
8.3.2 生成器表达式
在第四章 Python运算符和流程控制章节讲过,简化for和if语句,使用小括号()返回一个生成器,中括号[]生成一个列表。
回顾下:
# 生成器表达式
>>> result = (x for x in range(5))
>>> result
at 0x030A4FD0>
>>> type(result)
# 列表解析表达式
>>> result = [ x for x in range(5)]
>>> type(result)
>>> result
[0, 1, 2, 3, 4]
第一个就是生成器表达式,返回的是一个生成器,就可以使用next方法,来获取下一个元素:
>>> result.next()
0
>>> result.next()
1
>>> result.next()
2
......
python可迭代对象 迭代器生成器_第八章 Python可迭代对象、迭代器和生成器-阿里云开发者社区...相关推荐
- 阿里云rds mysql 并发_干货 | 浅析RDS MySQL 8.0语句级并发控制-阿里云开发者社区
背景 为了应对突发的数据库请求流量.资源消耗过载的语句访问.SQL 访问模型的变化, 并保持 MySQL 实例持续稳定运行,阿里云RDS for MySQL 8.0所采用的AliSQL分支设计了基于语 ...
- python email模块详解_python模块之email: 电子邮件编码解码 (一、解码邮件)-阿里云开发者社区...
python自带的email模块是个很有意思的东西,它可以对邮件编码解码,用来处理邮件非常好用. 处理邮件是一个很细致的工作,尤其是解码邮件,因为它的格式变化太多了,下面先看看一个邮件的源文件: Re ...
- python全局变量有缩进吗_Python全局变量和局部变量的问题 400 请求报错 -问答-阿里云开发者社区-阿里云...
# coding:utf-8 sum = 5 def add(x, y): print sum sum = x + y if __name__ == '__main__': add(7, 8) 上面的 ...
- apache camel 相关配置_使用apache camel从表中选择数据-问答-阿里云开发者社区-阿里云...
我希望能够使用Camel连续轮询数据库以从表中选择数据.我已经在我的Spring Boot应用程序中配置了Camel.这是我正在使用的配置 build.gradle: implementation ' ...
- nacos 本地测试_本地调试和服务器调试都无法连通-问答-阿里云开发者社区-阿里云...
本地调试和服务器调试都无法连通 anand 2018-11-20 16:30:31 4696 异常信息: com.alibaba.nacos.api.exception.NacosException: ...
- mysql double 存储_关于MYSQL中FLOAT和DOUBLE类型的存储-阿里云开发者社区
关于MYSQL中FLOAT和DOUBLE类型的存储 重庆八怪 2016-04-12 844浏览量 简介: 关于MYSQL中FLOAT和DOUBLE类型的存储 其实在单精度和双精度浮点类型存储中其存储方 ...
- xlsx模块 前端_纯前端利用 js-xlsx 之单元格样式(4)-阿里云开发者社区
0.单元格样式: 样式属性 子属性 取值 fill patternType "solid" or "none" fgColor COLOR_SPEC bgCol ...
- python画五角星和六角星程序_python画五角星和六角星程序-阿里云开发者社区
1.五角星 import turtle turtle.forward(100) turtle.right(144) turtle.forward(100) turtle.right(144) turt ...
- drawstring 文本居中_从Graphics.DrawString()居中输出文本
-问答-阿里云开发者社区-阿里云...
我正在使用.NETCF(Windows Mobile)Graphics类和将DrawString()单个字符呈现到屏幕的方法. 问题是我似乎无法使其正确居中.无论我为字符串渲染的位置的Y坐标设置什么, ...
- python实现迭代计算_带你读《强化学习:原理与Python实现》之三:有模型数值迭代-阿里云开发者社区...
第3章 有模型数值迭代 在实际问题中,直接求解Bellman期望方程和Bellman最优方程往往有困难.其中的一大困难在于直接求解Bellman方程需要极多的计算资源.本章在假设动力系统完全已知的情况 ...
最新文章
- 比买电脑还便宜的桌面虚拟化方案
- 如何在androidstudio中运行java程序
- BZOJ4589: Hard Nim(FWT 快速幂)
- 今晚直播 | 高效视频理解模型的设计及ICCV比赛冠军方案解读
- 微信小程序02【配置详解、生命周期-app对象使用、页面跳转详解】
- 如何定义和实现一个类的成员函数为回调函数
- [UE4]使用蓝图关闭对象的碰撞SetActorEnableCollision
- C/C++ 时间相关用法
- 对未来计算机的畅想初中英语,初中英语期中考试,作文停电一小时,在北京……在上海……在威海…….doc...
- Bookdown平台分享了哪些书籍,如何使用Bookdown分享书籍
- 怎样更改计算机ip用户名,无法修改系统IP地址
- Android 移动开发知识体系
- 访问k8s集群出现Unable to connect to the server: x509: certificate is valid for xxx, not xxx问题解决【详细步骤】
- 【一句日历】2019年8月
- 设置mathtype章节号显示与隐藏
- Matlab基础知识五
- LabVIEW使用POST调用有道翻译
- USB鼠标卡顿解决办法
- 利用photoprism搭建私有云相册
- 工商管理专业知识与实务(中级)【1】