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

......

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows Mobile下使用CppUnitLite输出测试结果

背景 TDD测试驱动开发是当前流行的开发方法及模式。遵循TDD的方法对开发程序库(Library)特别有用&#xff0c;因为Library就是为第三方提供一定功能接口的实现&#xff0c;使用TDD的方法可以预先为定义的接口提供测试案例&#xff0c;保证实现代码能通过测试&#xff0c;保证Li…

sql注意事项2点

①对Null的判断,如果要用<>与null判断,则都会得到否定结果②insert into时,要把字段显示指出,不然会因字段位置变化出错③-一个数时,如果有可能存在Null,则结果会被置为Null解决方法,select出来的结果,最好加isnull判断转载于:https://www.cnblogs.com/lishenglyx/archiv…

PHP IE中下载附件问题

重点&#xff1a; 1、在IE中下载附件之前要清空缓存。 2、中文文件名要用urlencode编码。 Header("Pragma: "); //不加的话&#xff0c;IE中会提示目标主机无法访问 Header("Cache-Control: "); //不加的话&#xff0c;IE中会提示目标…

10 个你可能还不知道 VS Code 使用技巧

经常帮一些同学 One-on-One 地解决问题&#xff0c;在看部分同学使用 VS Code 的时候&#xff0c;有些蹩脚&#xff0c;实际上一些有用的技巧能够提高我们的日常工作效率。NO.1一、重构代码VS Code 提供了一些快速重构代码的操作&#xff0c;例如&#xff1a;将一整段代码提取为…

使用MAP文件快速定位程序崩溃代码行(转)

作为程序员&#xff0c;平时最担心见到的事情就是程序发生了崩溃&#xff0c;无论是指针越界还是非法操作&#xff0c;都将给我们的应用系统造成巨大的损失。但在一个大型系统的测试过程中&#xff0c;初期出现程序崩溃似乎成了不可避免的事。其实测试中出现程序崩溃并不可怕&a…

构建安全的Xml Web Service系列之如何察看SoapMessage

上一篇文章地址&#xff1a;构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53) 要分析Xml Web Service的安全性&#xff0c;首先要解决的问题是我们能了解和清楚Soap消息的格式和内容&#xff0c;如果获得不了SoapMessage&#xff0c;分析如何能构建安全Xml w…

前端高效开发必备的 js 库梳理

之前有很多人问学好前端需要学习哪些 js 库, 主流框架应该学 vue 还是 react ? 针对这些问题, 笔者来说说自己的看法和学习总结.首先我觉得在学习任何知识之前必须要有一个明确的学习目标, 知道自己为什么要学它, 而不是看网上说的一股脑的给你灌输各种知识, 让你学习各种库, …

交叉报表crosstab隐藏列名显示_SAP软件 报表查询之 输出格式设置

SAP不仅是功能强大、逻辑严谨的ERP软件&#xff0c;还提供了强大的报表查询功能。SAP的ALV报表展示功能是SAP的一大特点&#xff0c;实现了类似于EXCEL的功能。使用好ALV报表功能可以方便用户从SAP中取到想要的数据&#xff0c;尤其是财务用户。大家在使用SAP报表时&#xff0c…

CSS HACK 区别 IE6、IE7、IE8、Firefox兼容性

转载链接&#xff1a;http://developer.51cto.com/art/201009/226787_1.htm 本文向大家描述一下如何使用CSS HACK区别IE6、IE7、IE8、Firefox兼容性问题&#xff0c;针对不同的浏览器写不同的CSS code的过程&#xff0c;就叫CSS hack,也叫写CSS hack&#xff0c;相信你对本文介…

Flex sdk4 布局与更新

在flex中,主要使用LayoutManager来驱动组件的度量和布局策略, LayoutManager实现一个单例,在Application类构造函数中创建: 1 public functionApplication()2 {3 UIComponentGlobals.layoutManager ILayoutManager(4 Singleton.getInstance("mx.managers::ILayoutManager&…

linux PROC文件系统详解

/proc文件系统下的多种文件提供的系统信息不是针对某个特定进程的&#xff0c;而是能够在整个系统范围的上下文中使用。可以使用的文件随系统配置的变化而变化。命令procinfo能够显示基于其中某些文件的多种系统信息。以下详细描述/proc下的文件。----------------------------…

seo每日一贴_白杨SEO:我看ZAC的外贸SEO应该怎样做?(策略篇)

前言&#xff1a;这是白杨SEO公众号更新第64篇。本该写写头条SEO啥的&#xff0c;最近在师徒培训讲站内SEO时有旁听同学提到后面讲讲谷歌SEO怎么样&#xff0c;因为谷歌全世界搜索市场占有率&#xff0c;所以外贸SEO最主要还是做谷歌SEO。以白杨特意又去了前辈ZAC的SEO每日一贴…

Can't connect to local MySQL server through socket '/tmp/mysql.sock'

转载链接&#xff1a;http://blog.csdn.net/ixidof/article/details/5958904 摘要&#xff1a;解决不能通过mysql .sock连接MySQL问题 这个问题主要提示是&#xff0c;不能通过 /tmp/mysql .sock连到服务器&#xff0c;而php标准配置正是用过/tmp/mysql .sock&#xff0c;但是…

[转]网页栅格系统研究(2):蛋糕的切法

[出自]http://lifesinger.org/blog/2008/10/grid-system-2/首先澄清一个应用场景问题。研究&#xff08;1&#xff09;中指出&#xff0c;对于结构复杂的网站&#xff0c;不少设计师们喜欢采用960固定宽度布局。但要注意的是&#xff0c;960并不是万能钥匙&#xff0c;大部分网…

Vue3响应式原理

关注若川视野&#xff0c;回复"pdf" 领取资料&#xff0c;回复"加群"&#xff0c;可加群长期交流学习本文结构- 关于Vue3- Vue2响应式原理回顾- Vue3响应式方案- Vue3响应式原理- 手写mini版Vue3响应式本文共计&#xff1a;2349字2图预计阅读时间&#xff…

python二值化 感兴趣区域_Python+OpenCV感兴趣区域ROI提取方法

方法一&#xff1a;使用轮廓步骤1"""src为原图"""ROI np.zeros(src.shape, np.uint8) #感兴趣区域ROIproimage src.copy() #复制原图"""提取轮廓"""proimagecv2.cvtColor(proimage,cv2.COLOR_BGR2GRAY) #转换成…

error while loading shared libraries: libmysqlclient.so.16: cannot open

转载链接&#xff1a;http://blog.sina.com.cn/s/blog_4ab24dd50100wnkv.html 问题解决办法&#xff1a; locate libmysqlclient.so.16 如我的mysql安装在/usr/local/mysql下&#xff0c;则结果为 /usr/local/mysql/lib/mysql/libmysqlclient.so.16 vi /etc/ld.so.conf 增…

编译cvaux错误的原因

平台vc6.0;在debug模式下编译cvaux时会提示三个错误&#xff1a;error C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvFGDStatModelerror C2039: foreground_regions : is not a member of CvGaussBG…

找准切入点,调试看源码,事半功倍

关注若川视野&#xff0c;回复"pdf" 领取资料&#xff0c;回复"加群"&#xff0c;可加群长期交流学习最近写了很多源码分析相关的文章&#xff0c;React、Vue 都有&#xff0c;想把我阅读源码的一些心得分享给大家。React&#xff1a;React 架构的演变 - 从…

Android布局大全

Android的界面是有布局和组件协同完成的&#xff0c;布局好比是建筑里的框架&#xff0c;而组件则相当于建筑里的砖瓦。组件按照布局的要求依次排列&#xff0c;就组成了用户所看见的界面。 所有的布局方式都可以归类为ViewGroup的5个类别&#xff0c;即ViewGroup的5个直接子类…