• day13迭代器和模块


    迭代器

    什么是迭代器
    1. 迭代器是容器型数据类型;
    2. 打印一个迭代器无法查看这个迭代器中所有的元素,迭代器无法通过len获取元素个数;
    3. 如果想要使用迭代器中元素,必须将元素从迭代器中取出,而且在取的时候只能从上往下按顺序,取一个就少一个,取出来的数据无法再放回迭代器。
    创建迭代器
    1. 用iter将其他序列转换成迭代器
    2. 创建生成器
    i1 = iter('abc')
    print(i1)    # 
    # print(len(i1))   # TypeError: object of type 'str_iterator' has no len()
    
    i2 = iter([10,20,30,40])
    print(i2)   # 
    # print(len(i2))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    迭代器的查操作

    不管以什么样的方式获取到了迭代器中元素,那被获取到的元素一定会从迭代器中消失

    1. 获取单个元素:next(迭代器)

      print(next(i1))      # 'a'
      print(next(i1))      # 'b'
      print(next(i1))      # 'c'
      # print(next(i1))    # StopIteration
      
      • 1
      • 2
      • 3
      • 4
    2. 遍历

      for x in i1:
          print(f'x:{x}')
      
      for x in i2:
          print(f'x:{x}')
      
      • 1
      • 2
      • 3
      • 4
      • 5
    3. 迭代器转换成列表

      i3 = iter('hello')
      result = list(i3)
      print(result)           # ['h', 'e', 'l', 'l', 'o']
      
      # print(next(i3))         # StopIteration
      
      • 1
      • 2
      • 3
      • 4
      • 5

    生成器

    什么是生成器
    1. 生成器是容器型数据类型(具备创建多个数据的能力,而不是保存多个数据的能力)

    2. 打印生成器无法查看所有的元素,生成器也不支持len操作。

    3. 如果需要使用生成器中的数据,必须将数据取出来,而且取一个就少一个。

    4. 生成器获取数据的方式和迭代器一样。

    创建生成器
    1. 生成器保存的并不是数据本身,而是产生数据的算法

    2. 怎么创建生成器:调用带有yield关键字的函数,就可以得到一个生成器。

      def func1():
          print('=====')
          print('+++++')
          if False:
              yield
          return 100
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    3. 如果被调用的函数的函数体中有yield,调用函数的时候不会执行函数体,也不会获取函数返回值,而是得到一个生成器对象(函数调用表达式的值就是生成器)

      result = func1()
      print(result)     # 
      # print(next(result))
      
      • 1
      • 2
      • 3
    定义生成器对应的函数
    1. 生成器创建数据的个数和数据的值,由在执行生成器对应的函数的函数体的时候会遇到几次yield,每次遇到yield的时候对应的数据来决定。
    2. 执行函数体会遇到几次yield对应的生成器就可以创建多个数据;
      每次遇到yield,yield后面的值是什么,对应的元素就是什么。

    示例1:

    def func2():
        yield 100
        yield 200
        yield 300
    
    
    gen2 = func2()
    print(next(gen2))      # 100
    print(next(gen2))      # 200
    print(next(gen2))      # 300
    # print(next(gen2))            # StopIteration
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    示例2:

    def func3(subject):
        for x in range(1,100):
            yield f'{subject}{x:0>3}'
    
    gen3 = func3('python')
    print(next(gen3))       # python001
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    生成器产生数据的原理

    调用函数创建生成器的时候不会执行函数体,获取生成器中的元素的时候才会执行函数体

    每次执行函数体的时候从开始位置开始,执行到yield就停下来,并且将yield后面的数据作为获取到的元素。

    def func4():
        yield 10
        yield 20
        yield 30
    
    gen4 = func4()
    print(next(gen4))    # 10
    print(next(gen4))    # 20
    print(next(gen4))    # 30
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    模块

    什么是模块

    python中一个py文件就是一个模块

    怎么在一个模块中使用另外一个模块的内容

    前提:被使用模块的模块名(py文件的文件名)必须符合变量名的要求
    使用原则:先导入才能使用(能被别的模块使用的内容只能是全局变量)

    导入模块

    test1.py:

    a = 100
    
    def func1():
        print('test中的函数')
    
    name = 'test'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. import 模块名 - 导入指定模块,导入后可以通过’模块名.xxx’这个模块中所有的全局变量

      import test1
      print(test1.a)        # 100
      print(test1.name)     # test
      test1.func1()         # test中的函数
      
      • 1
      • 2
      • 3
      • 4
    2. from 模块名 import 变量1,变量2,… - 导入指定模块中的指定变量,导入后可以直接使用所有指定的变量

      from test1 import a,func1
      print(a)
      func1()
      
      • 1
      • 2
      • 3
    3. from 模块名 import * - 导入指定模块中所有的变量,导入后可以直接使用所有变量

      from test1 import *
      print(a)
      print(name)
      func1()
      
      • 1
      • 2
      • 3
      • 4
    4. import 模块名 as 新模块名 - 导入模块的时候对模块重命名,通过’新模块名.xxx’的方式使用模块中所有的全局变量

      import test1 as t1
      test1 = 22
      print(t1.a,t1.name)   # 100 test
      t1.func1()            # test中的函数
      print(test1)          # 22
      
      • 1
      • 2
      • 3
      • 4
      • 5
    5. from 模块名 import 变量1 as 新变量1,变量2 as 新变量2,… - 对导入的变量重命名

      from test1 import a,name as tname
      name = '小明'
      print(a)        # 100
      print(name)     # 小明
      print(tname)    # test
      
      • 1
      • 2
      • 3
      • 4
      • 5
    导入模块的原理
    1. 不管以什么样式的方式导入了模块,或者模块中的内容。系统都会在导入模块的时候进入对应的模块,将模块中的代码全部执行。

    2. 原理存在的问题:可能存在在导入的时候执行一些没有必要执行的代码

    3. 导入模块的时候选择性执行代码:
      在被导入的模块中添加指定的if语句(if name == ‘main’),将不需要被别的模块执行的代码放入到这个if语句中

      if __name__ == '__main__':
          # 这个if语句中所有的代码不会被别的模块执行
          pass
      
      • 1
      • 2
      • 3

      实例:

      download.py:

      def download_film(name):
          print(f'{name}开始下载:')
          print('检查网络')
          print('链接服务器')
          print('传输数据')
          print('保存数据')
          print(f'电影{name}下载结束')
      
      if __name__=='__main__':
          for x in range(10):
              download_film(f'电影{x}')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      另外一个模块中调用:

      from download import download_film
      
      download_film('肖申克的救赎')
      
      """
      结果:
      肖申克的救赎开始下载:
      检查网络
      链接服务器
      传输数据
      保存数据
      电影肖申克的救赎下载结束
      """
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

    什么是包

    包就是包含__init__.py的文件夹

    包就是用来管理py文件,对py文件按照特定的方式进行分类。

    怎么使用包中的内容

    需要导入的包和模块:

    包:fileManager -> 模块:_init_.py、 operateFile.py、operateJsonFile.py

    包:files -> 模块:test2.py

    1. import 包名 - 导入指定的包(必须是包,文件夹无意义),导入后可以通过’包名.xxx’的方式使用__init__.py文件中所有内容

      import fileManager
      
      fileManager.create_file()     # 创建文件
      print(fileManager.m)          # 11
      
      • 1
      • 2
      • 3
      • 4
    2. import 包名.模块名 - 导入指定包中的指定模块(文件夹也可以)

      import fileManager.operateFile
      import files.test2
      
      fileManager.operateFile.open_file()
      fileManager.operateFile.close_file()
      
      print(files.test2.x)
      files.test2.func2()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      直接导入包中的模块,然后重命名:

      import fileManager.operateFile as file
      file.close_file()
      file.open_file()
      
      • 1
      • 2
      • 3
    3. from 包名 import 模块名1,模块名2,…

      from fileManager import operateFile, operateJsonFile as json
      operateFile.open_file()
      
      • 1
      • 2
    4. from 包名.模块名 import 变量1, 变量2,…

      from files.test2 import x, func2
      print(x)
      func2()
      
      • 1
      • 2
      • 3

    异常捕获

    异常

    异常就是错误。

    执行程序的过程中,会中断程序的执行(让程序提前结束)

    exit() - 让程序正常退出

    捕获异常

    异常捕获 - 让程序在出现异常的时候,不崩溃,还可以接着往后执行

    注意:不要滥用异常捕获,如果是因为使用者使用者不当导致程序出现异常,又希望在出现异常程序可以继续执行才使用异常捕获。

    1. 结构1

      a. 语法:

      try:
      代码段1(需要捕获异常的代码段)
      except:
      代码段2(捕获到异常需要执行的代码段)

      b. 执行过程:先执行代码段1,如果出现异常马上执行代码段2;如果没有出现异常,就不执行代码段2

      c. 实例:

      try:
          print('abc'[4])   # # IndexError
          print('=====')
          print('+++++')
      except:
          print('捕获到异常!')
      
      print('程序结束!')
      """
      捕获到异常!
      程序结束!
      """
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    2. 结构2 - 捕获指定异常

      try:
      代码段1(需要捕获异常的代码段)
      except 异常类型:
      代码段2(捕获到异常需要执行的代码段)

    3. 结构3 - 同时捕获多种异常

      try:
      代码段1(需要捕获异常的代码段)
      except (异常类型1, 异常类型2,…):
      代码段2(捕获到异常需要执行的代码段)

    4. 结构4 - 同时捕获多种异常

      try:
      代码段1(需要捕获异常的代码段)
      except 异常类型1:
      代码段11
      except 异常类型2:
      代码段22

  • 相关阅读:
    多亏了这个神器,让我斩获华为入场券
    新建stm32工程——基于标准库也就是库函数的方式
    Java线程池:并发编程的利器
    【修复版】2023新版塔罗 算八字测运易理风水 取名 源码平台 搭建教程
    OpenAI Codex,GitHub Copilot 和cheat.sh 三个代码建议工具对比
    全链路压测(10):测试要做的准备工作
    【STM32单片机】宠物定时喂食器设计
    「Kafka」监控、集成篇
    SpringCloud源码分析 (Eureka-Client-服务下架与服务下线) (四)
    2022-12-06两天学习总结
  • 原文地址:https://blog.csdn.net/lmj275871/article/details/126148257