python_笔记_day12_迭代器_生成器_模块_异常

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('程序崩溃前我还能抢救下数据')

你可能感兴趣的:(python_笔记_day12_迭代器_生成器_模块_异常)