一、复习
1.闭包:定义在函数内部的函数(被函数嵌套的函数) 2.装饰器:闭包的一个应用场景 -- 为一个函数添加新功能的工具 3.开放封闭原则:不能修改源代码,不能修改调用方式,但可以对外提供增加新功能的特性
小点:多个装饰器运行流程
def o1(func): def inner(*args, **kwargs): print('o1 ------------') # 1 result = func(*args, **kwargs) print('o1 ============') # 5 return result return inner def o2(func): def inner(*args, **kwargs): print('o2 ------------') # 2 result = func(*args, **kwargs) print('o2 ============') # 4 return result return inner @o1 @o2 def fn2(): print('fn2 ============') # 3 fn2() # 函数调用位置 # # 执行流程:函数调用位置 => o1装饰器inner => o2装饰器inner => 本体fn2 # # => 回到o2装饰器inner =>回到o1装饰器inner => 回到函数调用位置 ##可通过debug走一遍看具体流程
小点:多层嵌套的装饰器
def wrap(var): def outer(func): # outer的参数是固定的,就是被装饰的函数对象 print(var) def inner(*args, **kwargs): print(111111111111111) func(*args, **kwargs) print(333333333333333) return inner return outer # 1.调用wrap返回outer @wrap(0) # wrap(000) => outer => @outer => fn3 = outer(fn3) ##@wrap(0) 可看做是两种情况综合 先wrap(0),运行返回outer, ## 此时在运行@outer,接下来的是正常的装饰器节奏 def fn3(): print(222222222222222) #调用outer传入fn3返回inner给fn3 fn3() # # @wrap(000) # wrap(000) => outer => @outer => fn3 = outer(fn3) # # 3.调用fn3就是调用inner,在inner内部调用原fn3
二、迭代器
1、相关概念:
器:包含多个值得容器
迭代:循环反馈(一次从容器中取出一个值)
迭代器:从装有多个值的容器里取出一个值给外界
迭代器:从装有多个值得容器中一次取出一个值给外界
2、可迭代对象
对象:python中装有地址的一个变量
可迭代对象:该对象有_iter_()方法
可迭代对象通过调用_iter_()方法得到迭代器对象
3、迭代器对象
迭代器对象可以做到不依赖索引取值(一次从容器中取出一个值)
迭代器对象都存在_next_()方法,且通过该方法获取容器中的值,获取规则,从前往后一次一个
st1={3,2,6,5,9} #不清楚集合为什么打印的结果是从小到大,而其他不是 iter_obj=st1._iter_() print(iter_obj) #<set_iterator object at 0x00000000021E13A8> #迭代器对象取一个值就少一个值(重点掌握) print(iter_obj.__next__()) # 2 print(iter_obj.__next__()) # 3 print(iter_obj.__next__()) # 5 print(iter_obj.__next__()) # 6 print(iter_obj.__next__()) # 9 #print(iter_obj.__next__()) #再加上一个,超出其范围,会报错 StopIteration ter_obj=st1._iter_() #若不加上这个迭代器对象,会输出结果为空,上面 已经取完其值 while True: try: ele = iter_obj.__next__() print(ele) except StopIteration: # 此处的try except 用来除去异常 # print("取完了") # 因为会存在无限循环,但是值不够的情况 break
4、for 循环
自带异常处理的while循环,自动获取被迭代对象的迭代器对象(即不需要人为添加._next_())
# for循环迭代器:
# -- 1.自动获取被迭代对象的迭代器对象;
# -- 2.在内部一次一次调用__next__()方法取值;
# -- 3.自动完成异常处理
for v in obj:
print(v)
if v == 2:
break
print(obj.__iter__().__iter__().__iter__().__next__()) # 3 因为上面的for已经取了两个值
# print(obj.__iter__().__iter__().__iter__() is obj) # True
# 可迭代对象.__iter__()得到的是该对象的迭代器对象
# 迭代器对象.__iter__().__iter__()得到的就是迭代器对象本身
迭代器对象代码:
for v in 'abc'.__iter__(): print(v) 结果: a b c for v in 'abc'.__iter__(): print(v) 结果: a b c # 为什么此处可以重复打印? 因为第二次重新给字符串装换到了迭代器对象 因此可以重复使用,而不是上面取完值后,下面没有输出结果
with open('abc.txt', 'r', encoding='utf-8') as f: print(f.__next__()) print(f.__next__()) print(f.__next__()) #‘abc.txt’文件里存在多行数据,此时的print是一行打印一次,因此需要多个print
直接:
可迭代对象:即有有__iter__()方法的对象,调用该方法返回迭代器对象
str | list | tuple | dict | set | range() | file | 迭代器对象 | enumerate() | 生成器
迭代器对象:有__next__()方法的对象,也就是用该方法一次从迭代器对象中获取一个值,取出一个少一个
file | enumerate() | 生成器
重点:
1.从迭代器对象中取元素,取一个少一个,如果要从头开始去,需要重新获得拥有所有元素的迭代器对象
2.迭代器对象也有__iter__()方法,调用后得到的是自己本身(当前含义几个元素,得到的就只有几个元素的迭代器对象)
3、对于for循环迭代:
1.自动获取被迭代对象的迭代器对象
2.在内部一次一次调用__next__()方法取值;
3.自动完成异常处理
三、生成器
# 生成器:就是一个迭代器对象
# 包含yield关键字的函数就是生成器
# 该函数名()得到的是生成器对象,且不会执行函数体
# 在函数内部执行一次,在遇到下一个yield时停止,且可以拿到yield的返回值
def my_yield(): print('first') yield 1 print('second') yield 2 print('Third') yield 3 g=my_yield() next(g) next(g) next(g) #以下为结果: 只打印函数体 first second Third print(next(g) print(next(g) print(next(g) #以下为结果: 函数体和返回值都打印 first 1 second 2 Third 3
def my_yield(): print('first') yield 1 print('second') yield 2 print('Third') yield 3 for i in my_yield(): print(i) #下面为结果: first 1 second 2 Third 3 yields=my_yield() print(yields) #以下为结果: <generator object my_yield at 0x000000000216A390> yields=my_yield() print(list(yields)) #以下为结果: first second Third [1, 2, 3]
总结: 按 顺序打印函数体和返回值: for 循环 print(next(i)) 先打印函数体后打印返回值: print(list(i)) 用其他类型数据转换 直接打印函数体: next(i) 直接打印生成器地址: print(i) 建议日常使用for循环和next方式取值
四‘枚举对象 ’
enumerate
通过for迭代器 循环遍历 可迭代对象,需要知道迭代的索引
#从上一次停止的位置紧着往下走,在再遇到下一个yield时停止,且可以拿到yield的返回值
# 生成器可以被for循环迭代
ls = [1, 3, 5, 7, 9]
for i, v in enumerate(ls):
print(i, v)
结果:
0 1
1 3
2 5
3 7
4 9
小点:
dict={'a':1,'b':2}
lis=[]
for i in enumerate(dict):
lis.append(i)
print(lis)
#[(0, 'a'), (1, 'b')]
#此处可见 仅用一个值i就可将索引与对应的值导出
#可利用此种特性将数据成行打印
#也可利用两个参数,将其换行打印
所有评论(0)