python学习笔记(三)生成器和迭代器

生成器

在循环的过程中不断推算出后续的元素,用以节省空间,这种一边循环一边计算的机制,成为生成器:generator,带 yield!
方法一:把列表生成式的[]改成()

>>> L =  [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x *  x  for x in range(10))
>>> g
<generator object <genexpr> at 0x0000021F20CDF270>

next()函数 获得 generator的下一个返回值
比如next(g),每次计算下一个元素的值,直到没有 下一个元素时抛出stopiteration的错误。
但用 next()太麻烦了,基本不用,都是用for循环

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

斐波拉契数列就适合用函数打印

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

这样拿不到generator的return语句的返回值,如果想要拿到包含在stopiteration的 value 中,用try捕获:

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

杨辉三角

def triangles():
    yield [1]               #第一行
    yield [1,1]             #第二行
    res = [[1],[1,1]]       #结果集
    n = 2                   #当前行数
    while n:
        temp = []           #临时list
        temp.insert(0,res[n-1][0])  #前一行 的 第一个数
        temp.append(res[n-1][-1])   #前一行最后一个数
        i = 1               #i从1开始 
        while i < n:        #i小于n当前行-1
            temp.insert(i, res[n-1][i-1] + res[n-1][i]) #把中间部分的数给填满,填的是上一行的两个数相加
            i += 1
        res.append(temp)    #每完成一行,加入到结果集里面去
        n += 1              #当前行数加一
        yield temp          #暂停一次
        #调用
        def main():
    n = 0
    results = []
    for t in triangles():
        print(t)
        results.append(t)
        n = n + 1
        if n == 10:
            break
    if results == [
        [1],
        [1, 1],
        [1, 2, 1],
        [1, 3, 3, 1],
        [1, 4, 6, 4, 1],
        [1, 5, 10, 10, 5, 1],
        [1, 6, 15, 20, 15, 6, 1],
        [1, 7, 21, 35, 35, 21, 7, 1],
        [1, 8, 28, 56, 70, 56, 28, 8, 1],
        [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
    ]:
        print('测试通过!')
    else:
        print('测试失败!')


    print(results)

main()

迭代器

可直接 用于for 循环的对象统称为可迭代对象,用 isinstance()判断 对象是否可迭代
例如:

>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False

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

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

生成器都是iterator迭代器对象,但list、dict、str 虽然是iterable可迭代对象,却不是iterator迭代器。
把list、dict、str等Iterable强类型转换变成Iterator可以使用iter()函数:

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

iterator 对象可以被next()函数调用并不断返回下一个数据,我们不能提前知道序列的长度,只能每次next()按需计算下一个数据。所以这是惰性计算。它可以表示一个无限大的数据流,如全体自然数,而list就不行。
总结:
可作用与for循环的都是iterable可迭代对象。
可作用于next()的都是iterator迭代器,表示惰性计算的序列。
集合数据类型如list、dict、str等可通过iter()强类型转换成迭代器对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值