迭代器

迭代器用于:

  • for 循环
  • 构建和扩展集合类型
  • 逐行遍历文本文件
  • 列表推导、 字典推导和集合推导
  • 元组拆包
  • 调用函数时, 使用 * 拆包实参

解释器需要迭代对象x时,会自动调用iter(x);

内置的iter函数,有以下功能:

  1. 检查对象是否实现了 _iter _ 方法, 如果实现了就调用它,获取一个迭代器。
  2. 如果没有实现 _iter _ 方法,但是实现了 _getitem _ 方法,Python 会创建一个迭代器,尝试按顺序(从索引 0 开始)获取元素。
  3. 如果尝试失败,Python抛出TypeError异常,通常会提示"C objectis not iterable"(C 对象不可迭代),其中C是目标对象所属的类。

image

__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()函数,虽然调用时会返回一个生成器,但是这里并不使用;

参考

  1. 流畅的Python.
  2. https://www.cnblogs.com/MnCu8...
  3. http://www.cnblogs.com/xybaby...
  4. http://python.jobbole.com/87805/

Tom_Chou
6 声望0 粉丝