简简单单讲清楚Python迭代器与生成器

迭代

循环中执行一遍循环体且选择下一个进入循环体的变量的过程

迭代器

迭代器是定义__next__方法的对象。(并用StopIteration标识迭代的完成)

区分可迭代对象和迭代器

可迭代对象是含有iter()方法的对象。iter()方法返回一个迭代器。String, tuple, list,dict都是可迭代对象,因为它们都实现了iter()方法;但是他们都不是迭代器,因为它们都没有实现iter()方法。

>>> print('__iter__' in dir(list), '__iter__' in dir(tuple), '__iter__' in dir(dict), '__iter__' in dir(str))
True True True True
>>> print('__next__' in dir(list), '__next__' in dir(tuple), '__next__' in dir(dict), '__next__' in dir(str))
False False False False

for循环遍历可迭代对象的过程

for循环遍历可迭代对象时,首先调用iter方法,得到一个迭代器;之后反复对迭代器调用其next方法,直到捕捉到StopIteration异常。

>>> for _ in 'abc':
    print(_)

a
b
c

String, tuple, list不是迭代器,因为它们没有实现next方法。

>>> next('abc')
TypeError: 'str' object is not an iterator
>>> next([1])
TypeError: 'list' object is not an iterator
>>> next((1,2))
TypeError: 'tuple' object is not an iterator

用iter()函数,以String, tuple, list作为参数,可以创建一个迭代器。

>>> iter_s = iter('abc')
>>> next(iter_s)
'a'

自定义迭代器

下面这个类既是迭代器,又是可迭代对象。因为它同时实现了iter和next两个方法.

# 迭代类
class Fibs():
    def __init__(self,max):
        self.a = 0
        self.b = 1
        self.max = max
        self.count_next = 0
    def __iter__(self):
        print("__iter__() is called")
        return self
    def __next__(self):
        self.count_next += 1
        print("__next__() is called {}".format(self.count_next))
        fib = self.a
        self.a,self.b = self.b,self.a + self.b
        if fib > self.max:
            print("raise StopIteration")
            raise StopIteration
        return fib

生成器

生成器是一种在运行时生成值的迭代器。生成器只能完整遍历一次。

  1. 用Generator expressions表示一个生成器
    Generator expressions是在List comprehensions语法中用圆括号代替方括号
    可以认为圆括号中的for语句隐式定义了一个生成器函数
>>> g = (x**2 for x in range(4))
>>> type(g)

  1. 调用生成器函数将返回一个生成器
    生成器函数是使用yield语句的函数。
    和普通函数不同,生成器函数在调用时返回一个生成器。并且函数的真正运行,不是在函数调用时,而是在调用其返回的生成器时。
    生成器函数为生成器提供生成下一个迭代值的规则。每当生成器迭代一次,函数会运行至下一个yield语句,然后暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
    使用生成器的好处是可以为程序节约大量的内存。(比较一下:当需要迭代10000次时,一个含有10000个元素的列表占的内存要比生成器要大得多;因为生成器只是一段代码而已,其元素是每次迭代时动态生成的)
import sys
 
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

判断一个对象是否可迭代

from collections import Iterable

isinstance(<要判断的对象>, Iterable)
isinstance('abc', Iterable) #str是否可迭代
isinstance((x**2 for x in range(5)), Iterable) #generator是否可迭代
isinstance(123, Iterable) #整数是否可迭代

参考

http://www.runoob.com/python3/python3-iterator-generator.html
http://greenteapress.com/thinkpython2/html/thinkpython2020.html

你可能感兴趣的:(简简单单讲清楚Python迭代器与生成器)