Python-迭代器、生成器

迭代器

迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束(即可通过for循环遍历),其只能往前不会后退。他有两个基本的方法:iter() 和 next()。

  • iter(iterable): 用于对iterable创建迭代器对象
  • next(iterable): 可以输出迭代器的下一个元素

字符串,列表或元组对象都可用于创建迭代器

list=[1,2,3,4]
it = iter(list)    
print (next(it))   
print (next(it))
>>>
1
2

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

  • __iter__(self): 返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
  • __next__(self):返回下一个迭代器对象。
  • StopIteration: 用于标识迭代的完成,防止出现无限循环的情况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。
class Puke:

    def __init__(self):
        self.count = 0
        self.num = [0, 1, 2, 3, 4, 5, 6, 7, 8]

    def __iter__(self):
        return self

    def __next__(self):
        if self.count > 5:
            raise StopIteration
        else:
            self.count += 1
            return self.num[self.count-1]


k = Puke()
for x in k:
    print(x, end=" ")
>>>
0 1 2 3 4 5 

生成器

生成器的本质是一个返回迭代器的函数,只能用于迭代操作

通过列表生成式可以简单直接地创建一个列表,但是受到内存限制,列表容量肯定是有限的。创建一个包含100万个元素的列表,不仅占用很大的存储空间,而且如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator),生成器可以按需生成并“返回”结果,而不是一次性产生所有的返回值

要创建一个generator,有很多种方法。

方式一:

第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

num= [x*2 for x in range(10)]
generator1 =(x*2 for x in range(10))
print(num)
print(type(generator1))
print(generator1) #打印生成器,输出的是地址。
"""
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

 at 0x00000239FE00A620>
"""

创建mylist和gen的区别仅在于最外层的[]和(),mylist是一个list,而gen是一个generator。

我们可以直接打印出list的每一个元素,如果要打印generator可以通过generator的内置next()方法:

generator1.next()
#0
generator1.next()
#2
generator1.next()
#4
…………

generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,返回StopIteration的错误。

此外,可以用for循环来代替next()方式

for x in generator1:
    print(x,end=' ')
#0 2 4 6 8 10 12 14 16 18

方式二:

如果上述中的推算算法比较复杂,使用方法一无法实现的时候,可以使用函数来实现。比如斐波拉契数列使用列表生成式写不出来,但可以使用函数把它打印出来:

def fib(max):
    n = 0 
    a, b = 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1

fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这与generator的逻辑类似。

只需要把print b改为yield b,即可将fib函数变成generator:

def fib(max):
    n = 0 
    a, b = 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

generator和普通函数的执行流程区别在于:普通函数是顺序执行,遇到return语句或者最后一行函数语句就返回;generator在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

你可能感兴趣的:(Python-迭代器、生成器)