装饰器迭代器
今日内容:函数部分
无参装饰器:嵌套两层的闭包函数
有参装饰器:嵌套三层的闭包函数(***)
装饰器的语法糖
叠加多个装饰器的加载顺序与执行顺序
函数部分
迭代器
**储备知识1**
代码演示,把接收的参数格式原封不动的转交给其内部的函数
def index(x,y):
print(x,y)
def wrapper(*args,**kwargs):
index(*args,**kwargs) # index(1,2,z=3)
wrapper(1,2,z=3)
**储备知识2**
嵌套调用和嵌套定义
def outter():
def wrapper():
pass
**储备知识3:**
结论1:L-》E-》G-》B
结论2:名称空间的嵌套关系是在函数定义阶段扫描语法时生成的
**储备知识4:闭包函数**
def outter(x):
def wrapper():
print(x)
return wrapper
f=outter(222) # f=函数wrapper的内存地址
f()
**储备知识5:为函数体传参的两种方案
方案一:**
def wrapper(x):
print(x)
wrapper(111)
wrapper(222)
**方案二:**
def outter(x):
def wrapper():
print(x)
return wrapper
f = outter(111) #f = 函数wrapper的内存地址
f()
f = outter(222) #f = 函数wrapper的内存地址
f()
"""
**1 什么是装饰器**
装饰器就是装饰别人的工具,具体是指为被装饰者添加新功能
装饰器-》函数
被装饰者-》函数
**2 为何要用装饰器**
装饰器的核心思想:(开放封闭原则)
在不修改被装饰者源代码以及调用方式的前提下,为被装饰者添加新功能
**3 如何实现装饰器**
可以用闭包函数去实现装饰器
"""
被装饰者
import time
def index():
print('welcome to index page')
time.sleep(3)
index()
**方案一:问题-》修改了被装饰者的源代码**
import time
def index():
start = time.time()
print('welcome to index page')
time.sleep(3)
stop = time.time()
print(stop - start)
index()
**方案二:问题-》会造成代码冗余**
import time
def index():
print('welcome to index page')
time.sleep(3)
start = time.time()
index()
stop = time.time()
print(stop -start)
start = time.time()
index()
stop = time.time()
print(stop -start)
start = time.time()
index()
stop = time.time()
print(stop -start)
**# 方案三:问题-》修改了被装饰对象的调用方式**
import time
def index():
print('welcome to index page')
time.sleep(3)
def wrapper(func):
start = time.time()
func()
stop = time.time()
print(stop -start)
wrapper(index)
**# 方案四:我们用wrapper函数赋值给原函数名index,wrapper应该与原函数保持一致,
但是现在的问题是不一致**
import time
def index():
print('welcome to index page')
time.sleep(3)
def outter(func): # func = 最原始那个index函数的内存地址
def wrapper():
start = time.time()
func()
stop = time.time()
print(stop -start)
return wrapper
index = outter(index) # f=outter(最原始那个index函数的内存地址)
# f=函数wrapper的内存地址
# print(f)
index()
**方案五:让wrapper的参数与返回值与被装饰者保持一致**
import time
def index(x,y,z):
print('welcome to index page',x,y)
time.sleep(3)
return 123
def outter(func): # func = 最原始那个index函数的内存地址
def wrapper(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
stop = time.time()
print(stop -start)
return res
return wrapper
index = outter(index) # f=outter(最原始那个index函数的内存地址)
# f=函数wrapper的内存地址
res = index(111,222,333) # res = wrapper(111,222,333)
print(res)
**装饰器语法糖**
import time
from functools import wraps
def outter(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop - start)
return res
return wrapper
@outter # index = outter(index)
def index(x, y, z):
"""index函数的文档注释"""
print('welcome to index page', x, y)
time.sleep(3)
return 123
res = index(111, 222, 333)
print(res)
print(index)
help(index)
**装饰器模板**
**重点记忆:**
def outter(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
**举例使用**
def sayhi(func):
def wrapper(*args,**kwargs):
print('hello')
res = func(*args,**kwargs)
return res
return wrapper
def auth(func):
def wrapper(*args,**kwargs):
u = input('username>>>: ').strip()
p = input("password>>>: ").strip()
if u == 'egon' and p == '123':
res = func(*args,**kwargs)
return res
else:
print("认证失败")
return wrapper
@auth
def index():
print('index=========>')
index()
**1 什么是迭代器**
迭代器指的是迭代取值的工具
什么是迭代???
迭代是一个重复的过程,但是每一次重复都是基于上一次结果而继续的
names = ['egon','tom','lili','jack','xxx']
msg = "hello world"
dic = {'k1':111,'k2':2222,'k3':33333}
def foo(xxx):
i = 0
while i < len(xxx):
print(xxx[i])
i += 1
foo(names)
foo(msg)
foo(dic)
**2 为何要用迭代器**
1 为了找到一种统一迭代取值方案(适用于str、list、tuple、dict、set,文件对象)
2 节省内存
**3 如何用迭代器**
可迭代的对象iterable:
内置有__iter__方法的对象(str、list、tuple、dict、set,文件对象)
迭代器对象iterator:
内置有__iter__方法
内置有__next__方法
"abc".__iter__()
[1,23].__iter__()
(1,2,3).__iter__()
{'k1':111}.__iter__()
{1,2,3}.__iter__()
f = open('a.txt',mode='wt')
f.__iter__()
print(len("abc")) # "abc".__len__()
dic = {'k1':1111,'k2':2222,'k3':3333}
iter_dic = dic.__iter__() # iter_dic=iter(dic)
print(iter_dic)
print(iter_dic.__next__()) # print(next(iter_dic))
print(iter_dic.__next__())
print(iter_dic.__next__())
print(iter_dic.__next__()) # 报错
new_iter = dic.__iter__()
print(new_iter.__next__())
msg = "hello world"
iter_msg = msg.__iter__()
print(iter_msg.__next__())
print(iter_msg.__next__())
print(iter_msg.__next__())
print(iter_msg.__next__())
dic = {'k1': 1111, 'k2': 2222, 'k3': 3333,'k4':4444,'k5':5555}
iter_dic = iter(dic)
iter_dic.__next__()
print(iter_dic.__iter__().__iter__().__iter__() is iter_dic)
while True:
try:
print(next(iter_dic))
except StopIteration:
break
for x in dic:
print(x)
**例1:**
dic = {'k1': 1111, 'k2': 2222, 'k3': 3333,'k4':4444,'k5':5555}
iter_dic = iter(dic)
for k in iter_dic:
print(k)
print('='*50)
# iter_dic = iter(dic)
for k in iter_dic:
print(k)
**例2**
with open('a.txt',mode='rt',encoding='utf-8') as f:
for line in f:
print(line)
print('='*50)
for line in f:
print(line)
l = [1,2,3,4,5,6,7,8,9]
iter_l=iter(l)
yield可以返回多次值
def func():
print('hello1')
print('hello1')
print('hello1')
yield 111
print('hello2')
print('hello2')
print('hello2')
yield 222
print('hello3')
print('hello3')
print('hello3')
print('hello3')
yield 333
print('hello4')
print('hello4')
print('hello4')
print('hello4')
函数内但凡出现yield语法,我们再调用函数就不会立即触发函数体代码运行,
会返回一个生成器对象,生成器对象就是一种自定义的迭代器
g = func()
print(g)
g.__iter__()
g.__next__()
res=next(g)
print(res)
res=next(g)
print(res)
res=next(g)
print(res)
next(g)