欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

从零开始的Python学习Episode 12——迭代器&生成器

程序员文章站 2022-04-12 19:35:19
生成器 列表生成式 用于快速地生成一个列表 也可以用于生成函数结果的列表 迭代器 迭代器是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__()方法的对象都是迭代器。 拿斐波拉契数列作例子 这种用法会如果max的很大的话会占用特别多的内存,导致 ......

生成器

 

列表生成式

用于快速地生成一个列表

a = [x*x for x in range(1,9)]
print(a)

#输出[1, 4, 9, 16, 25, 36, 49, 64]

也可以用于生成函数结果的列表

def f(n):
    return n**3

a = [f(x) for x in range(1,9)]
print(a)

#输出[1, 8, 27, 64, 125, 216, 343, 512]

  

迭代器

迭代器是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__()方法的对象都是迭代器。

拿斐波拉契数列作例子

def fib(max): 
    l = []
    n, a, b = 0, 0, 1 
    while n < max: 
        l.append(b) 
        a, b = b, a + b 
        n = n + 1
    return l

  这种用法会如果max的很大的话会占用特别多的内存,导致程序卡顿。

使用迭代器可以解决复用可占空间的问题

迭代器可以通过 next() 不断返回数列的下一个数,内存占用始终为常数。

class fib(object): 
    def __init__(self, max): 
        self.max = max 
        self.n, self.a, self.b = 0, 0, 1 

    def __iter__(self): 
        return self 

    def next(self): 
        if self.n < self.max: 
            r = self.b 
            self.a, self.b = self.b, self.a + self.b 
            self.n = self.n + 1 
            return r 
        raise stopiteration()

  

生成器

生成器其实是一种特殊的迭代器。生成器(yield)既可以保持代码的简洁性,又可以减少占用内存的效果。它不需要再像上面的类一样写 __iter__() 和 __next__() 方法了,只需要一个 yiled 关键字。

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

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

#输出
1
1
2
3
5

  yield 的作用就是把一个函数变成一个生成器,带有 yield 的函数不再是一个普通函数,python 解释器会将其视为一个生成器,在 for 循环执行时,每次循环都会执行 fib 函数内部的代码,执行到 yield b 时,fib 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

(1)send()方法

send方法可以往生成器里传值

def f():
    print("ok")
    n = yield
    print(n)
    print("ok2")
    yield 2
f = f()
f.send(none)
f.send(1)
next(f)
#输出
ok
traceback (most recent call last):
1
ok2
  file "d:/pycharm project/test/starter/test2.py", line 10, in <module>
    next(f)
stopiteration

  send方法会把值传到yield前的对象,并往下执行到下一个yield。但当使用send之前要先用next或者用send(none)来获取yield的位置,否则无法把值传给yield。

还有一点:

在一个生成器中,如果没有return,则默认执行到函数完毕;如果遇到return,如果在执行过程中 return,则直接抛出 stopiteration 终止迭代。而for不报错的原因是内部处理了迭代结束的这种情况。

是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__() (python2中实现 next() )方法的对象都是迭代器