未加星标

第八章 Python可迭代对象、迭代器和生成器

字体大小 | |
[开发(python) 所属分类 开发(python) | 发布者 店小二03 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

8.1 可迭代对象(Iterable)

大部分对象都是可迭代,只要实现了__iter__方法的对象就是可迭代的。

__iter__方法会返回迭代器(iterator)本身,例如:

>>> lst = [1,2,3] >>> lst.__iter__() <listiterator object at 0x7f97c549aa50>

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

8.2 迭代器(Iterator)

具有next方法的对象都是迭代器。在调用next方法时,迭代器会返回它的下一个值。如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。

使用迭代器的好处:

1)如果使用列表,计算值时会一次获取所有值,那么就会占用更多的内存。而迭代器则是一个接一个计算。

2)使代码更通用、更简单。

8.2.1 迭代器规则

回忆下在Python数据类型章节讲解到字典迭代器方法,来举例说明下迭代器规则:

>>> d = {'a':1, 'b':2, 'c':3} >>> d.iteritems() <dictionary-itemiterator object at 0x7f97c3b1bcb0> # 判断是否是迭代器 >>> 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 "<stdin>", line 1, in <module> 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 "<stdin>", line 1, in <module> 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 "<stdin>", line 1, in <module> 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异常结束循环。

博客地址:http://lizhenliang.blog.51cto.com

QQ群: 323779636( Shell/Python运维开发群 )

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 <generator object fab at 0x7f2369495820>

可见,调用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 <generator object <genexpr> at 0x030A4FD0> >>> type(result) <type 'generator'&gt

本文开发(python)相关术语:python基础教程 python多线程 web开发工程师 软件开发工程师 软件开发流程

主题: Python数据博客变量
分页:12
转载请注明
本文标题:第八章 Python可迭代对象、迭代器和生成器
本站链接:http://www.codesec.net/view/484030.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 开发(python) | 评论(0) | 阅读(36)