迭代器和生成器、包和模块、异常捕获
迭代器
-
什么是迭代器(iter)
迭代器是容器型数据类型;
打印一个迭代器无法查看这个迭代器中所有的元素,迭代器无法通过len获取元素个数
如果想要使用迭代器中的元素,必须将元素从迭代器中取出,而且在取得时候只能从上往下按顺序,取一个少一个,取出来的数据无法再放回迭代器 -
创建迭代器
1)用iter将其他序列转换成迭代器
2)创建生成器
i1 = iter('abc') i2 = iter([10, 20, 30, 40]) print(i1, i2) # print(len(i1), len(i2)) # 报错!!!
-
迭代器的查操作
不管以什么样的方式获取到了迭代器中的元素,那被获取到的元素一定会从迭代器中消失
1)获取单个元素:next(迭代器)
print(next(i1)) # a print(next(i1)) # b print(next(i1)) # c # print(next(i1)) # 报错!!! print(next(i2)) # 10
2)遍历
for i in i1: print(i) for i in i2: print(i) # 20,30,40
3)迭代器转换成序列
i3 = iter('hello') result = list(i3) # ['h', 'e', 'l', 'l', 'o'] print(result) # print(next(i3)) # 报错!!!
生成器
-
什么是生成器
生成器是容器型数据类型(具备创建多个数据的能力,而不是保存多个数据的能力)。
打印生成器无法查看所有的元素,生成器也不支持len操作.
如果需要使用生成器中的数据,必须将数据取出来,而不是取一个少一个
生成器获取数据的方式和迭代器一样 -
创建生成器
生成器保存的并不是数据本身,而是产生数据的算法.
怎么创建生成器:调用带有yield关键字的函数,就可以得到一个生成器。
def func1(): print('----') print('====') if False: yield return 100 # 如果被调用的函数的函数体中有yield,调用函数的时候不会执行函数体,也不会获取函数返回值,而是得到一个生成器对象(函数调用表达式的值就是生成器) result = func1() print(f'result:{result}')
-
创建生成器对应的函数
生成器创建数据的个数和数据的值,由在执行生成器对应的函数的函数体的时候会遇到几次yield,每次遇到yield的时候对应的数据来决定
执行函数体会遇到几次yield对应的生成器就可以创建多少个数据;
每次遇到yield,yield后面的值是什么,对应的元素就是什么def func2(): yield 100 yield 200 yield 300 gen2 = func2() print(next(gen2)) print(next(gen2)) print(next(gen2)) # print(next(gen2)) # 报错!!! def func3(subject): for i in range(1, 100): yield f'{subject}{i:0>3}' gen3 = func3('python') print(next(gen3)) for i in gen3: print(f'i:{i}') print('分割线:', '==' * 50)
-
生成器产生数据的原理
调用函数创建生成器的时候不会执行函数体,获取生成器中元素的时候才会执行函数体。
每次在执行函数体的时候从开始位置开始,执行到yield就停下来,并且将yield后面的数据作为获取到的元素# 协程 def func4(): print('===1===') yield 10 print('===2===') yield 20 print('===3===') yield 30 gen4 = func4() print(next(gen4)) print('分割线:', '++' * 50) print(next(gen4)) print('分割线:', '++' * 50) print(next(gen4)) def get_file_data(): f = open('', encoding='utf-8') while True: data = f.readline() if not data: break yield data reader = get_file_data() print(next(reader))
模块
被导入模块test1
a = 100
def func1():
print('test中的函数')
name = 'test'
if __name__ == '__main__':
print('test___start')
for i in range(0, 10):
print(i)
print('test___end')
-
什么是模块 - python中的一个py文件就是一个模块
-
怎么在一个模块使用另外一个模块的内容
前提:被使用的模块的模块名(py文件的文件名)必须符合变量名的要求
使用原则:先导入才能使用(能被别的模块使用的内容只能是全局变量) -
导入模块
import 模块名 - 导图指定模块,导入后可以通过‘模块名.xxx’的方式使用这个模块中所有的全局变量
from 模块名 import 变量1,变量2,… - 导入指定模块中的指定变量,导入后可以直接使用所有指定的变量
from 模块名 import * - 导入指定模块中所有的变量,导入后可以直接使用所有变量
import 模块名 as 新模块名 - 导入模块的时候对模块重命名,通过’新模块名.xxx’的方式使用模块中的所有的全局变量
from 模块名 import 变量1 as 新变量1,变量2 as 新变量2,… - 对导入的变量重命名# ====导入方式1==== # import test1 # # print(test1.a) # print(test1.name) # test1.func1() # ====导入方式2==== # from test1 import name,a,func1 # # print(name) # print(a) # func1() # ====导入方式3==== # from test1 import * # # print(name) # print(a) # func1(10) # ====导入方式4:对模块重命名==== # import numpy as np # import test1 as t1 # # test1 = 22 # print(t1.a) # print(t1.name) # t1.func1() # ====导入方式5:对变量重命名==== # from test1 import a, name as tname # # name = '小明' # print(a) # print(name) # print(tname)
-
导入模块的原理
不管以什么样的方式导入了模块,或者模块中的内容。系统都会在导入模块的时候进入对应的模块,将模块中的代码全部执行
原理存在的问题:可能存在在导入模块的时候执行一些完全没有必要执行的代码
导入模块的时候选择性执行代码:
在被导入的模块中添加指定的if语句(if name == ‘main’:),将不需要被别的代码执行的代码放入到这个if语句中# import test1 # from test1 import a if __name__ == '__main__': # 这个if语句中的代码不会被别的模块执行 pass
包
-
什么是包
包就是包含__init__.py文件的文件夹
包就是用来管理py文件的,对py文件按照特定的方式进行分类.
-
怎么使用包中的内容
1)import 包名 - 导入指定的包(必须是包,文件夹无意义),导入后可以通过‘包名.xxx’的方式使用__init__中的所有全局变量
2)import 包名.模块名 - 导入指定包中的指定模块(文件夹也可以用)
3)from 包名 import 模块名1,模块名2,…
4)from 包名.模块名 import 变量1,变量2,…# ===直接导入包=== # import fileManage # # print(fileManage.x) # ===直接导入包中的模块,然后重命名=== # import files.test2 # # print(files.test2.x) # ===直接导入包中指定的多个模块=== # from fileManage import open,close # ===导入指定包中指定模块中的指定内容=== # from files.test2 import * # # print(func1()) # from files.manage.test2 import * # # print(func1()) from fileManage import funo, remove_file funo() remove_file()
__init___.py # 1.创建快捷键 from fileManage.open import funo # 2.封装通用工具 def remove_file(): print('删除文件')
异常捕获
-
异常
异常就是错误。
执行程序的过程中,如果出现异常,会中断程序的执行(让程序提前结束)
exit() - 让程序正常退出# print('===') # print('abc'[4]) # print('+++') # print('---')
-
异常捕获 - 让程序在出现异常的时候,不崩溃,还可以接着往后执行
注意:不要滥用异常捕获。如果是因为使用者使用不当导致程序出现异常,又希望在出现异常程序可以继续执行才使用异常捕获
结构1 - 捕获所有异常
try:
代码段1(需要捕获异常的代码段)
except:
代码段2(捕获到异常需要执行的代码段)
执行过程:先执行代码段1,如果出现异常直接马上执行代码段2;如果没有出现异常,就不执行代码段2
结构2 - 捕获指定异常
try:
代码段1(需要捕获异常的代码段)
except 异常类型:
代码段2(捕获到异常需要执行的代码段)
结构3 - 同时捕获多种异常
try:
代码段1(需要捕获异常的代码段)
except (异常类型1,异常类型2,异常类型3…):
代码段2(捕获到异常需要执行的代码段)
结构4 - 同时捕获多种异常,做出不同反应
try:
代码段1(需要捕获异常的代码段)
except 异常类型1:
代码段11
except 异常类型2:
代码段22try: print('abc'[0]) print('abc'[4]) except IndexError: print('捕获到异常') print('程序结束!') try: age = int(input('请输入年龄:')) if age >= 18: print('成年!') else: print('未成年!') except ValueError: print('年龄输入有误')