迭代器、生成器、包、模块、异常捕获
一、迭代器和生成器
-
迭代器(iter)
1.特点:
-
迭代器是容器型数据类型;
-
打印一个迭代器无法查看这个迭代器中所有的元素,迭代器无法通过len获取元素个数;
i1 = iter('abc') print(i1) # <str_iterator object at 0x000001BB58E7AE08> # print(len(i1)) # 报错:object of type 'str_iterator' has no len()
-
使用迭代器中的元素必须将元素从迭代器中取出,只能从上往下按顺序取,取一个少一个,取出来的数据无法放回迭代器;
2.创建
-
用iter将其他序列转换成迭代器
i1 = iter('abc') print(i1) # <str_iterator object at 0x000001BB58E7AE08> i2 = iter([1, 2, 3]) print(i2) # <list_iterator object at 0x000001BB59023548>
-
创建生成器
3.迭代器的查操作
-
获取单个元素:next()
i1 = iter('abc') print(i1) # <str_iterator object at 0x000001BB58E7AE08> i2 = iter([1, 2, 3]) print(i2) # <list_iterator object at 0x000001BB59023548> print(next(i1)) # 'a' print(next(i1)) # 'b' print(next(i1)) # 'c' # print(next(i1)) # 元素取完之后报错:StopIteration print(next(i2)) # 1
-
遍历
语法: for 变量 in 迭代器: 循环体
i2 = iter([1, 2, 3]) for x in i2: print(f'x:{ x}') # 结果: x: 1 x: 2 X: 3
-
迭代器转换成序列
i3 = iter('hello') result = list(i3) # 迭代器i3里的元素已经取完了,i3空了 print(result) # ['h', 'e', 'l', 'l', 'o']
-
-
生成器(yield)
1.生成器的特点- 生成器是容器型数据类型(具备创建多个数据的能力,而不是保存多个数据的能力)。
- 打印生成器无法查看所有元素,生成器不支持len操作。
- 使用生成器中的元素必须将元素从生成器中取出,取一个少一个。
- 生成器获取数据的方式和迭代器一样。
2.创建生成器:
- 生成器保存的并不是数据本身,而是产生数据的算法。
- 如果被调用的函数的函数体中有yield,调用函数时不会执行函数体,也不会获取返回值,而是得到一个生成器对象。
具体创建方法: 调用带有yield关键字的函数,就可以得到一个生成器。
def func1(): print('------') print('++++++') yield return 100 # 如果被调用的函数的函数体中有yield,调用函数时不会执行函数体,也不会获取返回值,而是得到一个生成器对象。 # (函数调用表达式的值就是生成器) result = func1() print(f'result:{ result}') # result:<generator object func1 at 0x000002273D4BA9C8>
3.定义生成器对应的函数
- 生成器创建数据的个数和数据的值,由在执行生成器对应的函数的函数体的时候会遇到几次yield,每次遇到yield的时候对应的数据来决定。
- 执行函数体会遇到几次yield,对应的生成器就可以创建多少个数据;
- 每次遇到yield,yield后面的值是什么,对应的元素就是什么。
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 print('==============华丽的分割线===============') def func3(subject): for x in range(1, 100): yield f'{ subject}{ x:0>3}' gen3 = func3('python') for i in gen3: print(i)
4.生成器产生数据的原理
调用函数创建生成器时不会执行函数体,获取生成器中的元素时才会执行函数体。
每次在执行函数体的时候从开始位置,执行到yield就停下来,并且将yield后面的数据作为获取到的元素。
二、包和模块
-
模块
1.概念:python中一个py文件就是一个模块
2.如何使用
- 前提:被使用的模块的模块名(py文件的文件名)必须符合变量名的要求
- 使用原则:先导入才能使用(能被别的模块使用的内容只能是全局变量)
3.导入模块
- import 模块名 ---- 导入指定模块,导入后可以通过’模块名.xxx’的方式使用这个模块中所有的全局变量。
# 导入1 import test1 print(test1.a) # 100 print(test1.name) # test test1.func1() # test1中的函数
- from 模块名 import 变量1,变量2,变量3,… ---- 导入指定模块中的指定变量,导入后可以直接使用所有的指定变量。
# 导入2 from test1 import a, func1 print(a) # 100 func1() # test1中的函数 # name 不能用,因为没有导入进来
- from 模块名 import * ---- 导入指定模块中的所有变量,导入后可以直接使用所有变量。
# 导入3 from test1 import * print(a) # 100 print(name) # test func1() # test1中的函数
- import 模块名 as 新模块名 ---- 导入模块时对模块重命名,通过’新模块名.xxx’使用模块中所有的全局变量。
# 导入4 import test1 as t1 print(t1.a) # 100 print(t1.name) # test
- from 模块名 import 变量1 as 新变量1,变量2 as 新变量2,变量3,… ---- 对导入的变量重命名。
# 导入5 - 对变量重命名 from test1 import a as na, func1 as f1 print(na) # 100 f1() # test1中的函数
4.导入模块的原理
不管怎样导入了模块or模块中的内容。系统都会在导入模块时进入对应的模块,将模块中的代码全部执行。
原理存在的问题:可能存在导入模块时执行一些没必要执行的代码。
解决方案:
导入时选择性执行代码:在被导入的模块中添加指定的if语句(if __name__ == '__main__'),将不需要被别的模块执行的代码放到这个if语句中。
if __name__ == '__main__': # 这个if语句中的代码不会被别的模块执行 pass
-
包
1.概念
包就是包 a含__init__.py文件的文件夹 包就是用来管理py文件,对py文件按照特定的方式进行分类。
2.包的创建
点击写python文件的目录右键->new->Python Package。
3.使用包
- import 包名
导入指定的包(必须是包,文件夹无意义),导入后可以通过'包名.xxx'的方式使用init.py文件中的所有内容。
# 导入1 import fileManager fileManager.create_file() print(fileManager.m)
- import 包名.模块名 ---- 导入指定包中的指定模块(文件夹也可以用)
# 导入2 import fileManager.operateFile import file.test2 fileManager.operateFile.create_file() fileManager.operateFile.close_file() print(file.test2.x) # 直接导入包中的模块然后重命名 import fileManager.operateFile as files files.close_file()
- from 包名 import 模块名1, 模块名2,… ---- 直接导入包中指定的多个模块
# 导入3 from fileManager import operateFile as file, operateJSONfile file.close_file()
- from 包名,模块名 import 变量1,变量2,变量3,… ---- 导入指定包中指定模块中的指定内容
# 导入4 from file.test2 import x print(x)
4.__init__的作用
- 创建快捷键
- 封装通用函数
三、异常捕获
-
异常
异常就是错误。 执行程序的过程中,如果出现异常,会中断程序的执行(程序提前结束)。 exit() - 让程序正常退出
-
异常捕获:让程序在出现异常的时候,不崩溃,还可以接着往后执行。
结构1:捕获所有异常 try: 代码段1(需要捕获异常的代码段) except: 代码段2(捕获到异常需要执行的代码段) 执行过程:先执行代码段1,如果出现异常直接马上执行代码段2;如果没有出现异常,就不执行代码段2。 结构2:捕获指定异常 try: 代码段1(需要捕获异常的代码段) except 异常类型: 代码段2(捕获到异常需要执行的代码段) 结构3:同时捕获多种异常 try: 代码段1(需要捕获异常的代码段) except(异常类型1,异常类型2,...): 代码段2(捕获到异常需要执行的代码段) 结构4:同时捕获多种异常并作出不同的处理。 try: 代码段1(需要捕获异常的代码段) except 异常类型1: 代码段11 except 异常类型2: 代码段22 except 异常类型3: 代码段33 ......
# 例1 结构1 try: print('abc'[4]) print('=====') except: print('捕获异常!') print('程序结束!') # 捕获异常! # 程序结束! # 例2 结构1 try: age = int(input('请输入年龄:')) if age >= 18: print('成年') else: print('未成年') except: print('年龄输入错误!') # 如果输入的是错误的年龄,会执行except中的代码,输入正确的年龄会正常执行输入年龄之后的代码。 # 结构2 try: print('abc'[4]) print('=====') except IndexError: print('捕获异常!')