day11复习
1. 匿名函数
- lambda 参数列表:返回值
2.函数作为变量
- 声明函数就是声明类型为function的变量,函数名是变量
- 函数作为参数(闭包),函数作为返回值
- sort\max\min 中的掌握key的使用
3.作用域
- 全局变量,和局部变量,global,nonlocal
global 变量名
变量名 = 值
一.迭代器
1. 函数的调用过程
- 函数的调用过程又叫压栈过程:每次调用函数,系统都会在内存的栈区间自动开辟一个临时的内存空间,
- 用来保存函数中声明的局部变量(其中形参也是保存在这个内存区域中的)
- 当函数调用结束,这个内存区域会自动销毁(这个内存中存储的数据也会销毁)
2. 迭代器(iter)
2.1什么是迭代器
- 迭代器python提供的容器类型的数据.(可变,有序 -- 不关注)
- 迭代器和之前的列表字典集合元组等容器不一样,它只能查看元素,而且看一个对于迭代器来说,里面的元素就会少一个
- 迭代器的值: a.将其他的数据转换成迭代器 b.生成器
- 迭代器的元素: 任何类型的数据都可以,可以重复
iter1 = iter('abc')
iter2 = iter([12, 32, 'abc'])
iter3 = iter([12, 32, 'abc', [0, 1],{'a':10},(1,2)])
2.2查 - 获取元素的值
- 注意: 不管以任何形式获取了迭代器中的某个元素值,这个元素都会从迭代器中消失
2.2.1获取单个元素
- next(迭代器)/迭代器.next() - 返回容器中最上面的元素
print(next(iter1))
print(next(iter1))
print(next(iter1))
# print(next(iter1)) StopIteration
- 注意当容器空了,再next会报错
2.2.2 遍历取出跌倒器中的每个元素
iter4 = iter('abcedfg')
for item in iter4:
print(item)
2.2.3什么时候使用迭代器:
- 多个数据中某个或者某些数据使用过了就不需要再保存了,这种数据就可以使用迭代器来保存.
二.生成器
1,什么是生成器:
- 生成器就是迭代器,但是迭代器不一定是生成器
- 如果函数中有yield关键字,那么这个函数就不再是一个普通的函数.
1.1怎么创建一个生成器
- 调用函数不在是执行函数体,获取返回值.而是创建这个函数对应的生成器对象
def nums():
for x in range(10):
yield 'a' + str(x)
gen1 = nums()
for x in gen1:
print(x)
1.2生成器怎么产生数据的
- 一个生成器能产生多少个数据,就看执行完生成器对应的函数体会遇到几次yield关键字
- 生成器是在获取数据的时候才会产生数据,执行生成器对应的函数的函数体,指定遇到yield为止,
- 将yield后面的数据作为生成器的元素返回,并且会记录这次产生数据函数体结束的位置,下次再产生数据的时候
- 会接着上次结束的位置接着往后执行...如果从函数开始到函数结束,没有遇到yield,那么就不会产生数据.
def nums2():
print('+++++++')
yield 'abc'
print('-------')
yield 100
for x in range(5):
yield x
# 创建一个生成器gen2
gen2 = nums2()
print(next(gen2))
print(next(gen2))
print(next(gen2))
- 练习 : 写一个生成器,能够产生'stuXXXX'的学号,stu0000 -- stu9999
def student_gen():
for x in range(10000):
yield 'stu' + str(x).zfill(4)
gen33 = student_gen()
print('==========')
for x in range(20):
print(next(gen33))
2.生成式
- 生成式是生成器的另一种写法(简写)
2.1语法1:
生成器变量 = (表达式 for 变量 in 序列) -- 结果是生成器
生成器变量 = [表达式 for 变量 in 序列] -- 结果是列表
- 表达式 - 可以是值,变量,运算表达式函数调用表达式等,只要不是赋值语句都可以
gen1 = ('stu'+str(x).zfill(4) for x in range(5))
print(next(gen1))
print(next(gen1))
2.2语法2:
生成器变量 = (表达式 for 变量 in 序列 if 条件语句)
###########################################
def 函数名():
for 变量 in 序列:
if 条件语句
yield 表达式
# gen2 = (x for x in range(10) if x % 2)
gen2 = ((x, x*2) for x in range(10) if x % 2)
print(list(gen2))
gen3 = ['num%d' % x for x in range(10) if x % 2]
print(list(gen3))
三.模块
python 中一个py文件就是一个模块
从封装的角度看: 函数是对功能的封装
模块可以通过多个函数对不同的功能封装,还可以通过全局变量对数据封装
0.模块的分类:系统模块(内置模块),第三方库(别人写的),自定义模块
1.模块的导入
a. import 模块名 /import 模块名 as 新的模块名
可以通过'模块名.'的方式去使用这个模块中所有的全局变量,模块名可以使用'as'改为新的的名字b. from 模块名 import 全局变量1 as 新名1,全局变量2 as 新名2,...
导入模块中指定的全局变量,导入后直接使用全局变量,全局变量名 as 新名来改变变量的名字,避免重名.注意: 重命名后,原名不能使用
========= 导入方式1 ========
# import keyword
# import random
# import math
# import test_moudule
# test_moudule.test1_1 *= 66.66
# print(test_moudule.test1_1)
# test_moudule.test1_fun1()
- ========= 导入方式2 ========
# from random import randint
# from test_moudule import test1_fun1, test1_1
# test1_fun1()
# print(test1_1)
- =========导入模块并重命名========
# import test_moudule as ts
# print(ts.test1_1)
# ts.test1_fun1()
- =========导入全局变量并重命名=========
# b = 'python'
# from test_moudule import b as t_b
#
# print(b, t_b)
2.导入模块的原理;
- 当代吗执行到import或者from -import的时候,会自动将对应的模块中的代码全部执行一遍
- include不会查重
- 同一个模块导入多次不会执行多次(放心导入!)
print('===========')
import test_moudule
import test_moudule
from test_moudule import b
test_moudule.test1_fun1()
3.阻止导入:
- 将需要阻止被别的模块导入的代码放到if语句中
if __name__ == '__main__':
需要阻止导入的代码段
- 原理: 每个模块都有一个属于自己的neme属性,来保存当前的模块名.默认情况下name的值就是模块
- 对应的py文件的文件名 .当我门直接运行某个模块的时候,对应的模块的__name__会自动变成'__main__',其他模块是默认值
四. 异常捕获
1.异常:
- 程序错误程序崩溃.程序中的某条语句出现异常,那么从这条语句开始,后面的代码不会执行,程序直接结束
2.异常捕获:
- 程序出现异常的时候,程序不崩溃
'''
方式1:捕获所有的异常
- a.语法
try:
代码段1
except:
代码段2
finally:
代码段n 不管什么情况代码段n都会执行,崩溃前也会执行,没有异常,也会执行
其他语句
- b.说明:
先执行代码段1,如果代码段1不出现异常,直接执行后面的其他语句如果出现异常就不崩溃
直接执行代码段2,然后再接着执行其他语句
# print('***********')
# # print(int('12a'))
# print('===========')
# print('..............')
#
# while 1:
# age = int(input('请输入年龄:'))
list1 = [1, 2, 3]
try:
print(list1[2])
except:
print('出现异常')
print('11111111111111')
方式2 捕获指定的一个或多个异常,做相同处理
try:
代码段1
except (异常类型1,异常类型2):
代码段2
其他语句
先执行代码段1,如果代码段1没出现异常,直接执行后面的其他语句
如果代码段1出现异常,如果这个异常的类型和需要捕获的异常类型一致,程序不崩溃,直接执行代码段2,然后再执行其他的语句
如果代码段出现异常,异常类型和需要捕获的异常类型不一致,程序直接崩溃
- 注意: 异常类型要求必须是直接或者间接继承至Exception类的子类
# print('=============方式2============')
# try:
# print([1,2,3][10])
# print({'a': 10}['b'])
# except KeyError:
# print('出现异常')
# # 崩溃
# try:
# print({'a': 10}['b'])
# print([1,2,3][10])
# except (KeyError, IndexError):
# print('出现异常')
# # 出现异常
# try:
# print([1, 2, 3][10])
# print({'a': 10}['b'])
# except (KeyError, IndexError):
# print('出现异常')
# # 出现异常
方式3 捕获不同类型的异常,并且可以对不同的异常做不同的处理
print('=============方式2============')
'''
try:
代码段1
except 异常类型1:
代码段2
except 异常类型2:
代码段3
其他语句
try:
print([1, 2, 3][10])
print({'a': 10}['b'])
except IndexError:
print('下标越界')
except KeyError:
print('key不存在')
finally:
3 finally: 不管什么情况代码段n都会执行,崩溃前也会执行,没有异常,也会执行
try:
代码段1
except:
代码段2
finally:
代码段n #不管什么情况代码段n都会执行,崩溃前也会执行,没有异常,也会执行
其他语句
try:
print([1, 2, 3][10])
print({'a': 10}['b'])
except KeyError:
print('key不存在')
finally:
print('程序崩溃前我还能抢救下数据')