迭代器
迭代器用于:
- for 循环
- 构建和扩展集合类型
- 逐行遍历文本文件
- 列表推导、 字典推导和集合推导
- 元组拆包
- 调用函数时, 使用 * 拆包实参
解释器需要迭代对象x时,会自动调用iter(x);
内置的iter函数,有以下功能:
- 检查对象是否实现了 _iter _ 方法, 如果实现了就调用它,获取一个迭代器。
- 如果没有实现 _iter _ 方法,但是实现了 _getitem _ 方法,Python 会创建一个迭代器,尝试按顺序(从索引 0 开始)获取元素。
- 如果尝试失败,Python抛出TypeError异常,通常会提示"C objectis not iterable"(C 对象不可迭代),其中C是目标对象所属的类。
__next__ #返回下一个可用的元素,如果没有元素了,抛出StopIteration异常
__iter__ #返回self, 以便在应该使用可迭代对象的地方使用迭代器,例如在for循环中
import re
RE_WORD = re.compile('\w+')
class Sentence:
# 可迭代的对象
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text)
def __iter__(self): # 1
return SentenceIterator(self.words)
class SentenceIterator:
# 迭代器
def __init__(self, words):
self.words = words
self.index = 0
def __next__(self): # 2
try:
word = self.words[self.index]
except IndexError:
raise StopIteration()
self.index += 1
return word
def __iter__(self): # 3
return self
s = Sentence('"The time has come," the Walrus said,')
for word in s:
print(word)
--------------------
The
time
has
come
the
Walrus
said
- {#}1: 实现__iter__方法,并返回了一个迭代器实例SentenceIterator,所以是可迭代的对象;
- {#}23: 实现__next__和__iter__,并返回了迭代器本身;
- {#}123:说明:迭代器可以迭代,但是可迭代的对象不是迭代器;
生成器
生成器函数
- 只要Python函数的定义体中有yield关键字,那么事实上定义的是一个generator function,调用这个generator function返回值是一个generator。
def gen_AB():
print('start')
yield 'A'
print('continue')
yield 'B'
print('end.')
print(gen_AB()) # 1
gen_AB() # 2
for item in gen_AB(): # 3
print('--->', item)
----------------
<generator object gen_AB at 0x0000016FDBBFDFC0>
start
---> A
continue
---> B
end.
- {#}1:虽然函数gen_AB没有return,但是依然返回了生成器对象;
- {#}2:此时没有执行函数gen_AB的内容;
- {#}3:生成器一定是迭代器(反之不成立);
- {#}3: 当调用generator的next方法,generator会执行到yield表达式处,返回yield表达式的内容,然后暂停(挂起)在这个地方,等待下个next的执行;
生成器表达式(generator expression)
- 生成器表达式可以理解为列表推导的惰性版本: 不会迫切地构建列表,
而是返回一个生成器, 按需惰性生成元素。
def gen_AB():
print('start')
yield 'A'
print('continue')
yield 'B'
print('end.')
res1 = [x*3 for x in gen_AB()] # 1
for i in res1:
print('-->', i) # 2
res2 = (x*3 for x in gen_AB()) # 3
for i in res2:
print('--->', i)
----------------
start
continue
end.
--> AAA
--> BBB
start
---> AAA
continue
---> BBB
end.
- {#}1:列表推导迫切迭代函数gen_AB,打印出start continue end. res1=[AAA,BBB];
- {#}2: 输出AAA,BBB;
- {#}3:把生成器表达式返回的值赋值给res2。只需调用gen_AB()函数,虽然调用时会返回一个生成器,但是这里并不使用;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。