Day 13
一、迭代器
1.什么迭代器(iter)
- 迭代器是容器型数据类型;
- 打印一个迭代器无法查看这个迭代器中所有的元素,迭代器无法通过len获取元素个数;
- 如果想要使用迭代器中元素,必须将元素从迭代器中取出,而且在取的时候只能从上往下按顺序,取一个就少一个,取出来的数据无法再放回迭代器。
2. 创建迭代器
- 用iter将其他序列转换成迭代器
i1 = iter('abc')
print(i1)
# print(len(i1)) # 迭代器无法通过len获取元素个数
- 创建生成器
3. 迭代器的查操作
-
不管以什么样的方式获取到了迭代器中元素,那被获取到的元素一定会从迭代器中消失
-
a. 获取单个元素: next(迭代器)
i1 = iter('abc')
print(next(i1)) # 'a'
print(next(i1)) # 'b'
print(next(i1)) # 'c'
print(next(i1)) # 报错! 超出迭代器中元素数量
- b. 遍历
i1 = iter('abc')
for x in i1:
print(f'x:{x}') # a b c
- c. 迭代器转换成序列
i3 = iter('hello')
result = list(i3)
print(result) # ['h', 'e', 'l', 'l', 'o']
二、生成器
1. 什么是生成器
- 生成器是容器型数据类型(具备创建多个数据的能力,而不是保存多个数据的能力)。
- 打印生成器无法查看所有的元素,生成器也不支持len操作。
- 如果需要使用生成器中的数据,必须将数据取出来,而且取一个就少一个。
- 生成器获取数据的方式和迭代器一样。
2.创建生成器
- 生成器保存的并不是数据本身,而是产生数据的算法。
- 怎么创建生成器:调用带有yield关键字的函数,就可以得到一个生成器。
def func1():
print('=====')
print('++++++')
if False:
yield
return 100
# 如果被调用的函数的函数体中有yield,调用函数的时候不会执行函数体,也不会获取函数返回值,而是得到一个生成器对象(函数调用表达式的值就是生成器)
result = func1()
print(f'result:{list(result)}')
'''
=====
++++++
'''
# print(next(result)) # 报错
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))
# 利用生成器每次运行函数产生一个学号
def func3(subject):
for x in range(1, 100):
yield f'{subject}{x:0>3}'
gen3 = func3('python') # python001
# 也可进行遍历获取所有学号
print(next(gen3))
for x in gen3:
print(f'x:{x}')
'''
x:python002
x:python003
x:python004
x:python005
....
x:python099
'''
4.生成器产生数据的原理
- 调用函数创建生成器的是不会执行函数体,获取生成器中的元素的时候才会执行函数体。
- 每次在执行函数体的时候从开始位置开始,执行到yield就停下来,并且将yield后面的数据作为获取到的元素。
def func4():
print('=======1=======')
yield 10
print('=======2=======')
yield 20
print('=======3=======')
yield 30
gen4 = func4()
print(next(gen4))
print('----')
print(next(gen4))
print('----')
print(next(gen4))
'''
=======1=======
10
----
=======2=======
20
----
=======3=======
30
'''
三、模块
1.模块 - python中一个py文件就是一个模块
2. 怎么在一个模块中使用另外一个模块的内容
- 前提:被使用的模块的模块名(py文件的文件名)必须符合变量名的要求
- 使用原则:先导入才能使用(能被别的模块使用的内容只能是全局变量)
3.导入模块
-
方法:
-
- import 模块名:导入指定模块,导入可以通过’模块名.xxx’的方式使用这个模块中所有的全局变量
** 首先我先创建一个test1.py文件 在文件中创建三个变量,在进行导入模块的操作**
test1.py
print('------------test1开始--------------')
a = 100
def func1():
print('test中的函数')
for x in range(10):
print(f'x:{x}')
name = 'test'
print('-------------test1结束-----------------')
# 在需要导入模块的文件进行导入操作
import test1
print(test1.a) # 100
print(test1.name) # 'test'
test1.func1() # 0 1 2 .... 9
-
- from 模块名 import 变量1,变量2,… - 导入指定模块中的指定变量,导入后可以直接使用所有指定的变量
from test1 import a, func1
print(a) # 100
func1() # 0 1 2 .... 9
print(test1.name) # 报错 因为我没有将name变量导入
-
- from 模块名 import * - 导入指定模块中所有的变量,导入后可以直接使用所有变量
from test1 import *
print(test1.a) # 100
print(test1.name) # 'test'
test1.func1() # 0 1 2 .... 9
-
- import 模块名 as 新模块名 - 导入模块的时候对模块重命名,通过’新模块名.xxx’的方式只用模块中所有的全局变量
import numpy as np
import test1 as t1
test1 = 22
print(t1.a, t1.name)
t1.func1()
-
- from 模块名 import 变量1 as 新变量1, 变量2 as 新变量2, … - 对导入的变量重命名
from test1 import a, name as tname
name = '小明'
print(a) # 100
print(name) # '小明'
print(tname) # 'test'
4. 导入模块的原理
-
不管以什么样式的方式导入了模块,或者模块中的内容。系统都会在导入模块的时候进入对应的模块,将模块中的代码全部执行。
-
原理存在的问题:可能存在在导入模块的时候执行一些完全没有必要执行的代码
-
导入模块的时候选择性执行代码:
-
在被导入的模块中添加指定的if语句(if name == ‘main’),将不需要被别的模块执行的代码放入到这个if语句中
四、包
1. 什么是包
- 包就是包含 ‘init.py’ 文件的文件夹
- 包就是用来管理py文件,对py文件按照特定的方式进行分类。
2.怎么使用包中的内容
- import 包名 - 导入指定的包(必须是包,文件夹无意义),导入后可以通过’包名.xxx’的方式使用__init__.py文件中所有内容
- import 包名.模块名 - 导入指定包中的指定模块(文件夹也可以用)
- from 包名 import 模块名1,模块名2,…
- from 包名.模块名 import 变量1, 变量2,…
五、异常捕获
1. 异常
-
异常就是错误。
-
执行程序的过程中,如果出现异常,会中断程序的执行(让程序提前结束)
-
补充:exit() - 让程序正常退出
print('==========')
print('abc'[4])
print('++++++++++')
print('----------')
'''
print('abc'[4])
IndexError: string index out of range
==========
'''
# 可以在控制台看到,等号打印出来 但是因为 'abc'[4] 错误 后面的结果均未打印
2.异常捕获 - 让程序在出现异常的时候,不崩溃,还可以接着往后执行
- 注意:不要滥用异常捕获。如果是因为使用者使用不当导致程序出现异常,又希望在出现异常程序可以继续执行才使用异常捕获。
结构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
try:
print('abc'[4]) # IndexError
print('=====')
print('+++++')
except:
print('捕获到异常!')
print('程序结束!')
try:
age = int(input('请输入年龄:')) # ValueError
if age >= '18':
print('成年!')
else:
print('未成年!')
except:
print('年龄输入有误!')