Python迭代器和生成器

参考链接
廖雪峰Python教程
名词区分:
可迭代对象(Iterable)
迭代器(Iterator)
迭代(Iteration)

一、可迭代对象Iterable
凡是可以用作for循环的都是可迭代对象,包括一般的list,tuple,set,dict,str.
可迭代对象本质是数据流,一个接一个的数据,但不一定像迭代器和生成器一样记住迭代到那个点, 下一个是什么, 利用iter(obj)函数可以将list等转变为迭代器(其实是生成器), 逐个元素投出.

my_string = "Yasoob"
my_iter = iter(my_string)
next(my_iter)
# 运行结果: 'Y'
my_string = "Yasoob"
my_iter = iter(my_string)
for i in my_iter:
    print(i)
#运行结果
Y
a
s
o
o
b    

判断一个对象是够是可迭代对象:

from collections import Iterable

print('字符串 is Iterable ?',isinstance('abc',Iterable))
print('list is Iterable ?',isinstance([1,2,3],Iterable))
print('整数 is Iterable ?',isinstance(123,Iterable))

#运行结果
字符串 is Iterable ? True
list is Iterable ? True
整数 is Iterable ? False

遍历可迭代对象的几种方法:

#遍历字符串:
for ch in 'abc':
    print(ch)

#遍历list
L = ['A','B','C']
for tmp in L:
    print(tmp)

for i,value in enumerate(L):
    print(i,':',value)

#遍历dict
d = {'1':'111','2':'222','3':'333'}
for key,v in d.items():
    print('key:',key,'value:',v)

二、迭代器(Iterator)对象
可以被next()函数调用并不断返回下一个值的对象称为迭代器. 生成器是一种迭代器.enumurate也是迭代器(本质生成器)
可以通过isinstance(obj, Iterator) (需要事先from collections import Iterable) 来判断对象是否迭代器.迭代到没有值了返回StopIteration错误.
for循环本质是通过调用可迭代对象的iter方法获取迭代器对象,再用next方法遍历元素.

可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False

三、generator生成器对象
生成器通过生成器函数产生, 生成器函数可以通过常规的def语句来定义, 不用return而是使用yield一次返回一个结果, 返回后停在相应位置, 再次调用时继续执行生成下一个结果, 当生成器结束没有下次执行时, 返回StopIteration.

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

>>> for n in fib(6):
...     print(n)
#运行结果
1
1
2
3
5
8

创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#(x for x in range(10))该表达式产生的是生成器对象,而非列表.
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
.
.
.
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

用for循环,因为generator也是可迭代对象

>>> g = (x * x for x in range(10))
>>> for n in g:
...     print(n)

四、list等的迭代器.
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter(obj)函数.
i.next()方法或next(i) 函数遍历迭代器
enumerate(i)

# 创建一个列表迭代器(listiterator)
i1 = iter([1, 2, 3])  # iter是Python BIF,用于生成迭代器,文档见底部
type(i1)
<type 'listiterator'>
i1
<listiterator object at 0x1cedf50>

# 创建一个字典项迭代器(dictionary-itemiterator)
d = dict(a = 1, b = 2)
i2 = d.iteritems()  # 生成iterator对象,对于字典来说还有iterkeys, itervalues等方法可用
i2
<dictionary-itemiterator object at 0x1dfe208>
[e for e in d.iteritems()]  # dict.iteritems方法生成的是迭代器元素为键值对形式
[('a', 1), ('b', 2)]

# 另外还有tuple/set等都可使用iter函数返回iterator对象
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

步进式访问迭代器中元素:obj.next()

i = iter(range[3])
i.next()
0
i.next()
1
next(i)  # next() - python2.6新增BIF,作用同iterator.next()
2
next(i)  # 无元素可迭代时,抛出StopIteration异常,可以通过捕获此异常判断是否迭代完毕
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

循环访问遍历迭代器

# 手动循环
try:
    while True:
        next(i)  # python2.6之前版本使用iterator.next()方法
except StopIteration:
    print 'Done'

# for循环
>>> i = iter(range(3))
# 以下句法叫做列表解析,这与生成器表达式类似,之后文章介绍生成器时再记
>>> [e for e in i]  # for在这里不断调用next函数,直到捕获StopIteration异常后退出
[0, 1, 2]

将迭代器传递给其他函数使用

>>> list(iter(range(3)))
[0, 1, 2]

帮助迭代器实现索引功能
使用enumerate函数返回一个迭代器对象, 该对象能够生产一个元组包括(索引,值).
enumerate(iterable, start=0)
第一参数是可迭代对象包括list/dict/迭代器等, 第二个参数是索引开始的号.

>>> i = iter('abc')  # python中字符串也是可迭代对象
>>> [(k, v) for k, v in enumerate(i)]  # enumerate返回一个元素为tuple的iterator
[(0, 'a'), (1, 'b'), (2, 'c')]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值