Python进阶内容--迭代器和生成器

什么是迭代器

在 Python 中,迭代器(Iterator)是一个访问集合元素的对象,它能够实现遍历集合的所有元素,而无需了解集合底层结构和细节。Python 中所有可迭代的对象(如 列表、元组、字符串、字典、集合等)都可以通过内置函数 iter() 获取对应的迭代器,然后使用内置函数 next() 逐个获取元素。当集合中的所有元素被遍历完成后,再次使用 next() 函数会抛出 StopIteration 异常。

什么是可迭代对象

在 Python 中,可迭代对象(Iterable)是指可以被迭代的对象,也就是包含多个元素并且支持使用 for 循环语句进行遍历的对象。Python 中许多内置的数据类型都属于可迭代对象,包括列表、元组、字符串、字典、集合等。

我们可以使用isinstance()方法和collections.abc中的Iterable类型来检查一个东西是否为可迭代对象。
例:

from collections.abc import Iterable
a = {
    
    1:"1",2:[1,2,3]}
print(isinstance(a,Iterable))
True

返回值为True

python内置类型中自带的迭代器

python中有很多内置类型就是可迭代对象,可迭代对象就说明这个东西可以通过iter()方法变为迭代器,举一个列表的例子。

a = [1,2,3]

a这个列表就是一个可迭代对象,我们先通过instance()方法检查这个列表是否为可迭代对象。

print(isinstance(a,Iterable))
True
for i in a:
	print(i)

在这里插入图片描述
这里其实就用到了可迭代对象的特性

注意:python在进行for 语句遍历循环的时候,会隐式的把需要遍历的对象转换成迭代器,并不断调用迭代器中的__next__()魔法函数,把迭代器中的对象一个一个的返回出来。

自定义可迭代器

class Iterable(object):
    def __init__(self):
        pass
    
    def __iter__(self):
        return self
    
    def __next__(self):
        pass
    
if __name__ == '__main__':
    i = Iterable()
        

这个是自定义迭代器的一个基本模板,除了初始化方法__init__()之外还有__iter__、next__两个魔法方法,这两个方法前者负责返回自身,所以它的返回值必须是self,而__next()方法负责迭代器主要的业务逻辑,需要根据不同的情况编写。

这里举一个经典的斐波那契额数列的例子:

class Fib:
    def __init__(self):
        self.prev,self.cur = 0,1

    def __iter__(self):
        return self

    def __next__(self):
        self.cur,self.prev = self.cur + self.prev,self.cur
        return self.cur


def fib():
    cur,prev = 1,0
    while 1:
        yield cur
        cur,prev = cur + prev,prev

if __name__ == '__main__':
    fib = Fib()
    for i in range(10):
        print(next(fib))

这段代码中的带yield的fib()函数是生成器函数

什么是生成器

生成器(Generator)是一种特殊的迭代器,它使用 yield 语句来产生值。与普通的迭代器相比,生成器更加简洁、高效,能够在遍历元素的同时动态生成新的元素,而不会像列表解析那样一次性占用大量内存空间。

def my_generator():
    yield 1
    yield 2
    yield 3
    yield 4

for item in my_generator():
    print(item) # 依次输出 1, 2, 3, 4

控制台会依次输出 1, 2, 3, 4

在这里插入图片描述

构建生成器的两种方式

上述代码是构建生成器的两种方式之一,也就是用函数来构建。

  • 生成器函数
    函数用yield返回值,这种函数叫生成器函数。函数被调用时会返回一个生成器对象。
def my_generator():
    yield 1
    yield 2
    yield 3
    yield 4

# for item in my_generator():
#     print(item) # 依次输出 1, 2, 3, 4
print(my_generator())
<generator object my_generator at 0x0000018F46583C10>

当打印这个执行函数时,控制台会返回这个信息,这个信息说明该函数返回的是一个generator (也就是生成器)对象。

生成器对象可以在当他被遍历的时候,自动调用__iter__()方法和__next__()方法,而且生成器是用一种懒加载的模式生成值,所以不需要担心生成器生成的值会一次性写入内存中,它会一个一个的写入内存。

  • 生成器表达式
g = (i for i in range(5))

用类似这样的表达式就能生成一个生成器,现在g就是一个迭代器,同时也是生成器。

from collections.abc import Iterable 
g = (i for i in range(5))
print(isinstance(g,Iterable))  # 返回值为True
print(iter(g))  # <generator object <genexpr> at 0x00000125451E3C10>

注意:生成器也可以是一个可迭代对象,因此我们可以遍历它:

for i in g:
    print(i)

在这里插入图片描述

yield与return的区别

  • 包含 return 的方法会以 return 关键字为最终返回,每次执行都返回相同的结果
  • 而包含yield方法的生成器每次执行时遇到 yield 就返回 yield 后的结果,但内部会保留上次执行的状态,下次继续迭代时,会继续执行 yield 之后的代码,直到再次遇到 yield 后返回

猜你喜欢

转载自blog.csdn.net/fuhao6363/article/details/130106584