• 一起看看Python中的迭代器&生成器


    每篇前言:


    可能很多看了我之前文章的小伙伴会说,我在前面的文章中不是都已经讲的很细了吗?为啥又出一篇文章来讲!
    俗话说得好,重要的事情说三遍,而我想说的是,重要的Python知识点要多讲!
    同时,本文又来了个新的很重要的知识点——生成器!

    1.迭代器(iterator)

    迭代是Python最强大的功能之一,是访问集合元素的一种方式。
    迭代器是可以记住遍历的位置的对象。
    迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问结束为止,迭代器只能往前不会后退。

    迭代是一个怎样的过程 ?

    • 就是一个依次从数据结构中拿出东西的过程~

    (1)列表推导式:能够简洁的构造一个新列表

    一般情况下这样构造一个新列表:

    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    li = []
    for i in range(1,10):
        li.append(i)
    print(li)               # 输出为:[1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    列表推导式:

    li1 = [i for i in range(1,10)]
    print(li1)              # 输出为:[1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    • 1
    • 2

    (2)升级篇 输出1-9之间的偶数 :

    (当然也可以使用range(1,10,2)

    li3 = [i for i in range(1,10) if i % 2 !=0]
    print(li3)              # 输出为:[1, 3, 5, 7, 9]
    
    • 1
    • 2

    (2)又升一级 如何打印出多个值呢?

    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    li4 = [(i,j) for i in range(1,5) for j in range(1,5)]
    print(li4)              # 输出为: [(1, 1), (1, 2), (1, 3), (1, 4),
                                     # (2, 1), (2, 2), (2, 3), (2, 4),
                                     # (3, 1), (3, 2), (3, 3), (3, 4),
                                     # (4, 1), (4, 2), (4, 3), (4, 4)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    集合推导式&字典推导式也就呼之欲出了:

    集合推导式:

    li5 = {i for i in range(1,10)}
    print(li5)				# 输出为:{1, 2, 3, 4, 5, 6, 7, 8, 9}
    
    • 1
    • 2

    字典推导式:

    li6 = {i:j for i in range(1,10) for j in range(1,10)}
    print(li6)				# 输出为:{1: 9, 2: 9, 3: 9, 4: 9, 5: 9, 6: 9, 7: 9, 8: 9, 9: 9}
    
    • 1
    • 2

    小拓展:

    li7 = {i:j for i,j in enumerate(['吴某','张某'])}
    print(li7)				# 输出为:{0: '吴某', 1: '张某'}
    
    • 1
    • 2

    注意:是没有元组推导式的!!!

    知识点补给站:

    • 迭代:
      for 迭代变量 in 可迭代对象
      每一次循环都会自动让“迭代变量”指向“下一个元素”。
    • 可迭代对象指:
      可迭代对象(实现了__iter__这个方法的都是):序列类型和散列类型。
    • 迭代器指:
      迭代器(实现了__iter__和__next__方法的就是,迭代器是一个对象) 只能前进不能后退。
    • 从可迭代对象生成一个迭代器:
      迭代器 = iter(可迭代对象)
      下个值 = next(迭代器)
      来个例子:

    列表是一个可迭代对象,dir查看列表方法的时候里面有__iter__方法,
    但列表不是一个迭代器,如何把列表转换为一个迭代器:

    li = [1,2,3,4]
    it = iter(li)
    
    • 1
    • 2

    获取迭代器的值?

     for i in it:
         print(i)			#这样会取到所有的值
    
    • 1
    • 2

    既然是迭代器了,就通过next方法去获取迭代器的值。这样做一次只取一个值,可以省内存空间。
    next两种使用方式:

    print(it.__next__())        # 输出为:1
    print(next(it))             # 输出为:2
    
    • 1
    • 2

    小拓展:

    • for循环实现原理。
    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    li = [1,2,3,4]
    it = iter(li)
    try:
        while True:
            print(next(it))
    except Exception as e:
        print(e)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出为:

    1
    2
    3
    4
    
    • 1
    • 2
    • 3
    • 4

    2.生成器(generator)

    问题一: 我们如何自己实现一个可迭代对象 ?

    在自定义的类中,要实现 __iter__ 魔术方法
    该魔术方法,必须要返回一个 迭代器
    (也需要自己实现)

    问题二: 是否有更加优雅的方式 ?

    生成器!

    • 生成器:返回迭代器的函数。

    (1)元组推导式

    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    tu = (i for i in range(1,10))
    print(type(tu))   			    # 输出为:<class 'generator'>      意思是这是个生成器
    print(dir(tu))      			# 可知tu里面有方法__iter__和__next__,所以这是个迭代器
    print(tu.__next__())  			# 既然是一个迭代器,就可以使用next方法取值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    (2)yield

    • 凡是有yield的函数都是生成器!

    返回这个对象
    yield 一个对象->暂停这个函数
    等待下次next重新激活

    来个例子:

    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    def fun():					# 定义生成器,由next函数触发执行
        print('好好学习')
        yield 1   				#返回一个1 并暂停函数
        print('天天向上')
        yield 2  				#返回一个2 并暂停函数
        print('再来一次')
        #没有代码了,引发StopIteration异常
    
    a = fun()
    aa = next(a)				# 输出为: 好好学习
    print(aa)					# 输出为: 1
    bb = next(a)				# 输出为: 天天向上
    print(bb)					# 输出为: 2
    # cc = next(a)				# 输出为: 再来一次 并抛出StopIteration异常(大家可以自行run一下看看哦~)
    #如果print(type(fun())),会输出<class 'generator'>,可见这个函数已经是一个生成器了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    再来个例子看看:

    # -*- coding: utf-8 -*-
    """
    __author__ = 孤寒者
    """
    def fun(ele, n):
        count = 0
        while True:
            if count < n:
                count += 1
                yield ele
            else:
                break
    
    
    a = fun('wumou', 5)
    for i in a:
        print(i)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    迭代器生成器总结:

    生成器 与 迭代器 的区别:

    • 生成器,是Python提供的一种非常简便的语法能让我们来自己写出迭代器。
      注意——> 生成器,是一种特殊的迭代器。
    • 生成器指的是一个函数,返回的结果是一个迭代器。
      而迭代器是一个对象。
  • 相关阅读:
    【MySQL】MySQL操作库
    卷积神经网络(一)
    [Common c/c++] 生产者消费者模型 using mutex/cv/semaphore
    B. Polycarp Writes a String from Memory
    No146.精选前端面试题,享受每天的挑战和学习
    2022年Java面试题整理归纳(持续更新)
    字节跳动开源Linux 内核网络抓包工具 netcap
    java---------上转型与下转型对象
    JavaSE泛型讲解
    06-Go语言中数组和切片
  • 原文地址:https://blog.csdn.net/qq_44907926/article/details/125488375