Python 学习笔记3 - 高级特性

2017-09-11  本文已影响0人  WesleyLien

生成器 generator

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的

生成器可以通过一边循环一边计算的机制,在循环的过程中不断推算出后续的元素,不必创建完整的list,从而节省大量的空间

简单的 generator 定义例子:

# 把一个列表生成式的[]改成(),就创建了一个generator
g = (x * x for x in range(10))

通过next()函数可获得generator的下一个返回值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的错误

next(g)

使用for循环获得generator的返回值,因为generator也是可迭代对象。使用for循环不需要关心 StopIteration 的错误

for n in g:
    print(n)

用类似列表生成式的for循环无法实现的时候,还可以用函数来实现 generator。如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator

// 输出斐波那契数的 generator
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
# 和前面一样,获取返回值的两种方式

f = fib(6)
next(f)

for n in fib(6):
    print(n)

generator 和函数的执行流程区别:

如果想要拿到 generator 的return语句的返回值,必须捕获 StopIteration 错误,返回值包含在 StopIteration 的 value 中。因为for循环获取不到 StopIteration 错误,所以只能用 next():

g = fib(6)

while True:
    try:
        x = next(g)
        print('g:',x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break

迭代器 Iterator

可以被 next() 函数调用并不断返回下一个值的对象称为迭代器:Iterator

Iterator 对象可以 被next() 函数调用并不断返回下一个数据,直到没有数据时抛出 StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算

因此,generator 都是 Iterator 对象,但 list、dict、str 虽然是 Iterable ,却不是 Iterator

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

可以使用 iter() 函数把list、dict、str等 Iterable 变成 Iterator

isinstance(iter([]), Iterator) ==> True
isinstance(iter('abc'), Iterator) ==> True
上一篇 下一篇

猜你喜欢

热点阅读