**多层装饰器**
需求:执行index()前,先认证,认证完成后计算index函数执行的时间
```python
dict = {'user':'egon', 'pwd':'123'}
import time
#装饰器
def auth(func):
def inner():
user=input('用户名:').strip()
pwd=input('密码:').strip()
if user==dict['user'] and pwd==dict['pwd']:
def bestinner(*args,**kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print('花费:%s' % (end - start))
return res
return bestinner
else:
print('用户名密码有误')
return inner
@auth
def index():
time.sleep(1)
print('呵呵')
return 'index返回值'
index()()
```
```python
import time
user_dic = {'is_login':None}
def outter(func): # func = 最原始的login函数的内存地址
def get_time(*args, **kwargs): # args = ('egon',) kwargs = {}
start = time.time()
res = func(*args, **kwargs) # 最原始的login函数的内存地址() 直接调用 func('egon')
end = time.time()
print('func run time:%s'%(end-start))
return res
return get_time
def login_auth2(data_source,x,t):
# data_source = 'file'
def login_auth(func):
# func = index
def inner(*args,**kwargs): # 这里的参数是跟被装饰函数的参数一一对应
if user_dic['is_login']:
res = func(*args, **kwargs)
return res
else:
if data_source == 'file':
username = input('please input your username>>>:').strip()
password = input('please input your password>>>:').strip()
if username == 'jason' and password == '123':
user_dic['is_login'] = True
res = func(*args,**kwargs)
return res
else:
print('username or password error')
elif data_source == 'MySQL':
print('from MySQL')
elif data_source == 'ldap':
print('ldap')
else:
print('暂无该数据来源')
return inner
return login_auth
# 装饰器在装饰的时候 顺序从下往上
# 装饰器在执行的时候 顺序从上往下
# res = login_auth2('MySQL')
@login_auth2('file',1,2) # index = login_auth(get_time) index = inner函数的内存地址
# @login_auth
@outter # get_time = outter(index) index是最原始的index
def index():
time.sleep(1)
print('index')
return 'index'
index()
```
**生成器**
```python
"""
生成器:用户自定义的迭代器,本质就是迭代器
"""
def func():
print('first')
yield 666 # 函数内如果有yield关键字,那么加括号执行函数的时候并不会触发函数体代码的运行
print('second')
yield 777
print('third')
yield 888
print('forth')
yield
yield
# yield后面跟的值就是调用迭代器__next__方法你能得到的值
# yield既可以返回一个值也可以返回多个值 并且多个值也是按照元组的形式返回
g = func() # 生成器初始化:将函数变成迭代器
print(g)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(range(1,10))
for i in range(1,10,2):
print(i)
```
```python
# yield支持外界为其传参
def dog(name):
print('%s 准备开吃'%name)
while True:
food = yield
print('%s 吃了 %s'%(name,food))
# def index():
# pass
# 当函数内有yield关键字的时候,调用该函数不会执行函数体代码
# 而是将函数变成生成器
# g = dog('egon')
# g.__next__() # 必须先将代码运行至yield 才能够为其传值
# g.send('狗不理包子') # 给yield左边的变量传参 触发了__next__方法
# g.send('饺子')
"""
yield
1.帮你提供了一种自定义生成器方式
2.会帮你将函数的运行状态暂停住
3.可以返回值
与return之间异同点
相同点:都可以返回值,并且都可以返回多个
不同点:
yield可以返回多次值,而return只能返回一次函数立即结束
yield还可以接受外部传入的值
"""
```
```python
# 列表生成式
# res = [i for i in range(1,10) if i != 4]
# print(res)
# res = (i for i in range(1,100000000) if i != 4) # 生成器表达式
# print(res)
# """
# 生成器不会主动执行任何一行代码
# 必须通过__next__触发代码的运行
# """
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
# print(res.__next__())
# 占内存
# f = open('xxx.txt','r',encoding='utf-8')
# data = f.read()
# print(len(data))
# f.close()
# with open('xxx.txt','r',encoding='utf-8') as f:
# # n = 0
# # for line in f:
# # n += len(line)
# # print(n)
# g = (len(line) for line in f)
# # print(g.__next__())
# # print(g.__next__())
# # print(g.__next__())
# # print(g.__next__())
# print(sum(g))
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g=test()
for n in [1,10]:
g=(add(n,i) for i in g)
# 第一次for循环g=(add(n,i) for i in test())
# 第二次for循环g=(add(n,i) for i in (add(n,i) for i in test()))
print(n)
res=list(g)
"""
for i in (add(10,i) for i in test()): 会执行所有的生成器内部的代码
add(n,i)
"""
#A. res=[10,11,12,13]
#B. res=[11,12,13,14]
#C. res=[20,21,22,23] 答案
#D. res=[21,22,23,24]
```