异步与并发基础:python迭代器和生成器

本文详细介绍了Python中的可迭代对象、迭代器和生成器的概念及其应用。包括如何使用类创建迭代器,生成器的基本原理及yieldfrom的使用,帮助读者深入理解Python迭代机制。

可迭代对象(Iterable)

  • 可迭代对象(Iterable)指可以使用for语句直接遍历的数据类型,如list,tuple,dict,set,str,还有generator(生成器),和带yield的函数,统称为可迭代对象(Iterable),
  • 可迭代对象必须实现__iter__()方法
from collections import Iterable
print(isinstance([], Iterable))
print(isinstance((), Iterable))
print(isinstance({}, Iterable))
print(isinstance("abc", Iterable))
print(isinstance((x for x in range(10)), Iterable)) # 生成器也是可迭代对象
print(isinstance(10, Iterable)) # 数字不是可迭代对象

迭代器(Iterator)

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

  • 使用类创建迭代器

    • 使用类创建迭代器必须实现 __iter__()__next__() 两个方法

    • __iter__()方法返回迭代器对象本身,而可迭代对象的该方法则返回其迭代器。

    • __next__()方法返回容器的下一个元素,在结尾时引发StopIteration异常

    class MyNumbers:
      def __iter__(self):
        self.a = 1
        return self
     
      def __next__(self):
        if self.a <= 20:
          x = self.a
          self.a += 1
          return x
        else:
          raise StopIteration
     
    myclass = MyNumbers()
    myiter = iter(myclass)
     
    for x in myiter:
      print(x)
    
  • 使用序列数据创建迭代器

    from collections import Iterator
    X = [1,2,3,4,5]
    print(type(X))
    Y = iter(X)
    print(type(Y))
    print(next(Y))
    print(next(Y))
    print(next(Y))
    
  • 迭代器和可迭代对象的区别

    • 需要同事实现了__iter____next__方法
    • 可迭代对象:只需实现了__iter__方法即可
    • 因此,迭代器是一个可迭代对象,但是可迭代对象不一定是一个迭代器
  • 迭代器和 列表、元组、集合、字符串这些区别:

    • 它们都属于可迭代对象,因为它们都实现了__iter__方法
    • 列表这些类型中的元素是真实存在于内存中的,而迭代器保存的是生成这些元素的算法,是惰性计算的程序流,在需要时计算给出即可,因此迭代器可以大大节省内存
  • 问题:list是一个可迭代对象,并没有实现__next__()方法,那么是怎么迭代的呢?
    我们先看下面代码:

from collections.abc import Iterator, Iterable

l = [1, 2, 3]
print(isinstance(l, Iterable))  # True
print(isinstance(l, Iterator))  # False

print(isinstance(l.__iter__(), Iterable))  # True
print(isinstance(l.__iter__(), Iterator))  # True

可以看到虽然list本身不是迭代器,但它的__iter__()方法返回了一个迭代器,因此可以for循环可以在此迭代器基础上调用__next__()方法进行迭代

生成器

生成器迭代器的子集,生成器一定是迭代器,但是迭代器不全是生成器。在Python中一个函数可以用yiled或yiled from替代return返回值,这样的话这个函数就变成了一个生成器对象。

  • 通过函数创建(生成器函数)

    def fib(number):
        """
        菲波那切数列
        :param number: 要获取的数量
        :return: 
        """
        a, b = 1, 1
        for i in range(number):
            yield a
            a, b = b, a + b
    
    
    gen = fib(5)
    print(gen)
    print(type(gen))
    for n in gen:
        print(n)
    
  • yield from

    • yield from是一个表达式,用于生成器嵌套,返回生成器的return值,可以代替for ... in ... : yield
    • 代码更加简洁
    • 可以用于生成器嵌套
    • 易于异常处理
    def demo1():
        yield 1
        yield 2
        return 3
    
    
    # def demo2():
    #     yield 4
    #     for i in demo1():
    #         yield i
    
    
    def demo2():
        """
        除了具备上面的功能,还能将demo1的返回值作为yield from表达式的值返回
        :return:
        """
        yield 4
        res = yield from demo1()
        print("通过yield from 获取生成器返回值:", res)
    
    
    gen = demo2()
    for i in gen:
        print('生成器yield的值:', i)
    """
    生成器yield的值: 4
    生成器yield的值: 1
    生成器yield的值: 2
    通过yield from 获取生成器返回值: 3
    """
    
    
  • 生成器表达式

    X = [1, 2, 3, 4, 5]
    it = [i for i in X]
    gen = (i for i in X)
    print(type(X))
    print(type(it))
    print(type(gen))
    
    # 输出
    """
    <class 'list'>
    <class 'list'>
    <class 'generator'>
    """
    

关系图

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值