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

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‘>

# 列表解析表达式
>>> result = [ x for x in range(5)]
>>> type(result)
<type ‘list‘>
>>> result
[0, 1, 2, 3, 4]

第一个就是生成器表达式,返回的是一个生成器,就可以使用next方法,来获取下一个元素:

>>> result.next()
0
>>> result.next()
1
>>> result.next()
2
......
时间: 2024-08-06 16:05:33

第八章 Python可迭代对象、迭代器和生成器的相关文章

11.Python初窥门径(函数名,可迭代对象,迭代器)

Python(函数名,可迭代对象,迭代器) 一.默认参数的坑 # 比较特殊,正常来说临时空间执行结束后应该删除,但在这里不是. def func(a,l=[]): l.append(a) return l print(func(1)) # [1] print(func(2)) # [1,2] print(func(3)) # [1,2,3] 二.函数名的应用 函数名指向的是函数的内存地址,加上()就执行这个函数 def func(args): return args print(func) #

python高级编程之迭代器与生成器

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #迭代器与生成器 #--------------------------------------- #迭代器基于2个方法 """ next:返回容器下一个项目 __iter__:返回迭代器本身 """ #通过内建函数和序列来创建 i=iter('abc') print i.next()#a print i.next(

python函数五(迭代器,生成器)

一.迭代器 1.可迭代对象(只含有__iter__方法的数据是可迭代对象) 常见的可迭代对象:str list tuple dict set range 1.1什么是可迭代对象? 方法一: dir(被测对象) 如果 他含有'__iter__ ',那这个对象就叫做可迭代对象.遵循可迭代协议 s = 'alex' l = [1,2,3,4,5] print('__iter__' in dir(s)) print('__iter__' in dir(l)) # 输出结果: # True # True

python当中的 可迭代对象 迭代器

学习python有一段时间了,在学习过程中遇到很多难理解的东西,做一下总结,希望能对其他朋友有一些帮助. 完全是个人理解,难免有错,欢迎其他大神朋友们批评指正. 1 迭代 什么是迭代呢??我们可以这样理解,一个容器类型的数据,比如 列表[ ]  .元组 () 和 字典 { }, 我们可以把这样类型的数据放入for temp in [1,2,3] 当中,temp 被一次一次的赋值成为后面容器内数据,然后我们拿到temp进行一些想做的事情.那么for 循环中自动的帮我们把数据一次一次的取出来,可以理

Python高级特性:迭代器和生成器 -转

在Python中,很多对象都是可以通过for语句来直接遍历的,例如list.string.dict等等,这些对象都可以被称为可迭代对象.至于说哪些对象是可以被迭代访问的,就要了解一下迭代器相关的知识了. 迭代器 迭代器对象要求支持迭代器协议的对象,在Python中,支持迭代器协议就是实现对象的__iter__()和next()方法.其中__iter__()方法返回迭代器对象本身:next()方法返回容器的下一个元素,在结尾时引发StopIteration异常. __iter__()和next()

Python(day8)迭代器、生成器

一 什么是迭代 1 重复 2 下一次重复是基于上一次的结果 # while True: # cmd=input('>>: ') # print(cmd) # l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) # count+=1 # # l=['a','b','c','d'] # for count in range(len(l)): # print(l[count]) # d={'a':1,'

python基础知识7——迭代器,生成器,装饰器

迭代器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁.这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件 特点: 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容

Python 函数式编程之迭代器、生成器及其应用

python 标准库中提供了 itertools, functools, operator三个库支持函数式编程,对高阶函数的支持,python 提供 decorator 语法糖. 迭代器 (iterator)和生成器(generator)概念是 python 函数式编程的基础,利用迭代器和生成器可以实现函数式编程中经常用到的 map(), filter(), reduce() 等过程以及 itertools, functools 中提供的绝大部分功能. 1.迭代器和生成器基础(next, ite

Python之容器、迭代器、生成器

1.容器.可迭代对象.迭代器.生成器概念 1. 容器:存储许多元素的数据结构.通常存储在内存(迭代器.生成器是特例)可以使用in来判断某个元素是否在存在的对象都是容器 举个例子:容器就像一个箱子,里面可以存放许多东西,我可以往这个箱子存取东西,可以判断这个箱子是否有某样东西 2.可迭代对象:可以使用iter()变成迭代器的对象都是可迭代对象,大部分容器都是可迭代对象(str,set,list,tuple,打开状态的files,sockets等等) 3.迭代器:它是一个带状态的对象,保存当前记录状