• Python学习之迭代器和生成器


    迭代器

    在Python如果一个对象可被循环(遍历)该对象中每一个元素的过程叫做迭代。例如 ,字典、字符串、列表、元祖、集合等。他们可被迭代的原因是,都有一个共同的内置函数__iter__。通过执行内置对象的__next__函数,可以依次打印该对象的所有元素。例如 有一个列表,该列表存储了1-100的数值,但是我们只想打印前50的个元素。

     1 flag=True
     2 l=[x for x in range(1,101)]
     3 
     4 l_iter = l.__iter__()
     5 while flag:
     6     try:
     7        item=l_iter.__next__()
     8        if item==51:
     9            flag=False
    10            break
    11        else:
    12            print(item)
    13 
    14     except:
    15         break

    在While循环中迭代器将一直循环执行__next__()函数,但迭代器本身并不知道它要迭代多少个元素。当执行到最后元素时,还会继续执行__next__()函数,但此时没有元素可被迭代了,由于迭代器找不到可被迭代元素,将会报错。因此我们在使用while循环时,配合异常捕获代码 try except一起使用,当迭代过程中出现异常,将会自动停止下一次循环。

    用迭代器生成列表(2.7版本有效)

     1 class TestIterator:
     2     value=0
     3     def next(self):
     4         self.value+=1
     5         if self.value>10: raise StopIteration
     6         return self.value
     7     def __iter__(self):
     8         return self
     9 ti=TestIterator()
    10 ret=list(ti)
    11 print(ret)

    输出结果:

    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    生成器:

    假设我们 有个需求,除第一个 和第二个元素外,其他元素依次为前两个元素之和。

    我们可以这样写

     1 def fib1(max):
     2     n,a,b=0,0,1
     3     while n<max:
     4         print(b)
     5         a,b=b,a+b
     6         n=n+1
     7     return 'done'
     8 
     9 a=fib1(5)
    10 print(a)

    输出结果

    1 1
    2 1
    3 2
    4 3
    5 5
    6 done

    推导过程如图

    用另外一种方法

    1 def fib2(max):
    2     n,a,b=0,0,1
    3     while n<max:
    4         yield b
    5         a,b=b,a+b
    6         n=n+1
    7     return 'done'

    调用该函数

    1 a=fib2(5)
    2 print(a)

    输出结果 1 <generator object fib at 0x0000000002800518> 

    此时我们发现,不能像之前那样直接显示结果,此时定义的fib并不是一个简单的函数,而是被改造成了生成器。如果想知道生成的结果可以依次执行__next__函数,但每次只返回一个结果,当没有更多的元素可以被迭代时将会抛出异常。

    另外我们也可以使用for 循环和while(需配合try  except使用)打印结果。

    1 a=fib2(5)
    2 for c in a:
    3     print(c)

    显示输出结果 1 1 2 3 5.

    使用生成器的好处:生成器是根据推导的过程计算下一个元素。再看前两个函数 fib1 和fib2 ,fib1在计算机中开辟一个固定的内存空间用于存储完整的计算结果,但如果我们想访问计算结果中的某一个元素,就需要先遍历整个计算结果,才能通过对象下标或者用for 循环和if条件判断 拿到我们想要的结果,这样做的可以实现我们的需求,但将会耗损较多的内存空间。而fib2则是依据推算过程计算出下一个元素,因此我们就可以在未创建完整对象之前获取我们想要的元素。从而降低内存消耗。

  • 相关阅读:
    JavaScript丨数组元素反转
    Executor框架浅析
    索引相关
    关系型数据库
    Cookie和Session
    HTTP和HTTPS
    TCP,UDP,HTTP
    OSI模型
    剑指Offer19
    剑指Offer03
  • 原文地址:https://www.cnblogs.com/SunIan/p/9710784.html
Copyright © 2020-2023  润新知