python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > python迭代器和生成器

python迭代器和生成器的区别解析

作者:.似水

文章介绍了可迭代对象和迭代器的概念及区别,以及生成器的定义、使用方法和特性,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

1.迭代器

1.1 可迭代对象

        可迭代对象指的是 实现了__iter__方法的对象,可以被for循环遍历的容器,比如一个列表,自定义的链表等。使用 iter() 方法获取它的迭代对象(可以理解为链表的指针)

1.2 迭代器

        迭代器是指实现了 __iter__ 和 __next__方法对象,__iter__返回它本身,确保每个单独的节点都是可以被迭代的,满足链表可以从第n个元素开始访问的需求;__next__返回它的下一个节点,如果已经遍历完毕则抛出StopIteration异常。

# 实现了__iter__方法,是一个可迭代对象,可以理解为是一个整的链表,但此时还不能单独访问其中的元素
class Node:
    def __init__(self, data):
        self.data = data
        self.next: Node | None = None
    def __iter__(self):
        return NodeIter(self)
#是迭代器对象,可以理解为指向链表首元素的指针,通过这个指针遍历所有的链表元素
class NodeIter:
    def __init__(self, node: Node = None):
        self.current = node
    def __iter__(self):
        return self
    def __next__(self):
        if self.current is None:
            raise StopIteration
        else:
            node = self.current
            self.current = self.current.next
            return node #返回当前节点的值

1.3 可迭代对象和迭代器的区别

依旧以链表举例,整个链表是一个可迭代对象,遍历这个对象的时候实际上是通过一个指向链表首元素的指针不断地移动到下一个元素来完成的,这个指针就可以理解为迭代器。

2.生成器

2.1 概念

        生成器是一种特殊的迭代器,它通过 yield 关键字动态的返回值,而非一次性返回所有值,适合用来读取大文件或产生无限序列。生成器内部自动实现了 __iter__和__next__.

当一个函数内部使用了yield关键字时,那么它就是一个生成器函数,此时函数的返回值不再是return后的返回值,而是类似于函数的对象 :

<generator object fibonacci at 0x0000026E4B6D20A0>

以一个生成n个斐波那契的生成器举例:

def fibonacci(limit):
    """生成斐波那契数列"""
    a, b = 0, 1
    count = 0
    while count < limit:
        yield a
        a, b = b, a + b
        count += 1

当执行下面的代码时:

fibo = fibonacci(10)
print(fibo) #输出:<generator object fibonacci at 0x0000026E4B6D20A0>
print(next(fibo)) #输出0
print(next(fibo)) #输出1
print(next(fibo)) #输出1
print(next(fibo)) #输出2

fibo是一个生成器对象,这个对象可以生成10个斐波那契数,但不是同时生成在内存中,而是一个next()取回一个值,这个特性被称作 "惰性加载" 。执行第一个next()时,返回第一个yield后的值并且暂停函数的执行,等到第二次执行next()时从第一个field后开始继续执行,也就是说,当我在第一个 yield下面抛出异常,函数执行一次 next()并不会报错,因为抛出异常语句并没有执行,第二次执行next()才会报错,比如下面的代码:

def generator1():
    print('第一个yield之前的语句块')
    yield 1
    print('第一个yield之后的语句块')
    print(1 / 0)
    print('第二个yield之前的语句块')
    yield 2
    print('第二个yield之后的语句块')
ge = generator1() #产生了一个生成器对象
print(next(ge))  # 只执行 print(1 / 0) 之前的代码函数就被中断了,所有不会报错
print(next(ge))  # 回到第一个yield之后的代码继续执行,执行到print(1 / 0)语句,报错

如果生成器函数中有return语句,return语句依旧有结束函数运行的作用,return之后的语句不可达,但仍然遵循上面的中断原则,并且return后的值是抛出 StopIteration异常的提示信息:

2.2 yield from

        当我们的生成器的数据是从一个列表中取得并且每次返回一个元素时应该怎么写?

def generator():
    user_list = ["zhang","li","wang","qian"]
    for username in user_list:
        yield username
ge = generator()
for i in ge:
    print(i)

yield from就是简化上面的流程,提升生成器的效率,以上代码可以用下面的代码替代:

def generator():
    user_list = ["zhang","li","wang","qian"]
    yield from user_list
ge = generator()
for i in ge:
    print(i)

到此这篇关于python迭代器和生成器的区别解析的文章就介绍到这了,更多相关python迭代器和生成器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文