装饰器相关
高阶函数的两种情况:
1、
把一个函数名当成实参传给另外一个函数(在不修改被装饰函数源代码的情况下,为其添加功能)
import time
def bar():
time.sleep(2)
print('in the bar')
def test1(fun_name):
t1 = time.time()
fun_name()
print('run time:%s'%(time.time()-t1))
test1(bar)
2、
返回值中包含函数名(不修改调用方式)
import time
def bar():
time.sleep(2)
print('in the bar')
def test1(fun_name):
return fun_name
bar = test1(bar)
bar()
高阶函数+嵌套函数则得到装饰器
import time
def timer(fun_name):
def deco():
start_time = time.time()
fun_name()
end_time = time.time()
print('running time:%s' % (end_time - start_time))
return deco
def bar():
time.sleep(2)
print('in the bar')
bar = timer(bar)
bar()
但我们一般把装饰器在被装饰函数前面定义,并且用如下的写法代替:
import time
def timer(fun_name):
def deco():
start_time = time.time()
fun_name() # 在这里调用是bar()这个函数
end_time = time.time()
print('running time:%s' % (end_time - start_time))
return deco
@timer # bar = timer(bar) 这步其实是调用了timer()这个函数,把bar这个函数进行重新定义
def bar():
time.sleep(2)
print('in the bar')
bar() # 在调用bar的时候,其实调用的是deco()这个函数
可以理解为,先用第一种高阶函数加上想要的功能,再重新覆盖定义这个函数,再用函数嵌套,就得到了我们想要的装饰器的效果
如果有参数:
import time
def timer(fun_name):
def deco(*args,**kwargs):
start_time = time.time()
fun_name(*args,**kwargs)
end_time = time.time()
print('running time:%s' % (end_time - start_time))
return deco
@timer # bar = timer(bar)
def bar():
time.sleep(2)
print('in the bar')
@timer
def bar2(name,age):
print(name,age)
bar()
bar2('simon',22)
终极版:原函数带有返回值,装饰器本身带参数
__author__ = "Alex Li"
import time
user, passwd = 'alex', 'abc123'
def auth(auth_type):
print("auth func:", auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
if auth_type == "local":
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = func(*args, **kwargs) # from home
print("---after authenticaion ")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
elif auth_type == "ldap":
print("搞毛线ldap,不会。。。。")
return wrapper
return outer_wrapper
def index():
print("welcome to index page")
@auth(auth_type="local") # home = wrapper()
def home():
print("welcome to home page")
return "from home"
@auth(auth_type="ldap")
def bbs():
print("welcome to bbs page")
index()
print(home()) # wrapper()
bbs()
几个装饰器的小练习和写的答案
一:编写3个函数,每个函数执行的时间是不一样的,
提示:可以使用time.sleep(2),让程序sleep 2s或更多,
二:编写装饰器,为每个函数加上统计运行时间的功能
提示:在函数开始执行时加上start=time.time()就可纪录当前执行的时间戳,函数执行结束后在time.time() - start就可以拿到执行所用时间
三:编写装饰器,为函数加上认证的功能,即要求认证成功后才能执行函数
四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
提示:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
答案:
# -*- coding: utf-8 -*-
import time, os
if not os.path.exists('login_for Decorator.txt'):
with open('login_for Decorator.txt', 'w', encoding='utf-8')as f:
f.write(str({'name': 'simon', 'password': '123'}))
with open('login_for Decorator.txt', 'r', encoding='utf-8')as f2:
dict_list = eval(f2.read())
name, password = dict_list['name'], dict_list['password']
login_status = 0
# 验证是否登录,一次登录,后面不再需要登录则可以运行
def login(func):
def deco(*args, **kwargs):
global login_status
if not login_status:
if_wrong = 1 # 默认密码是错误的
while if_wrong: # 如果输入错误,就一直循环输入
_name = input('your name :').strip()
_password = input('type your password:').strip()
if _name == name and _password == password:
print('welcome %s login' % _name)
login_status = 1
if_wrong = 0
func()
else:
pass # print('不应该出现这个')
else:
func()
return deco
# 此装饰器的作用是打印函数运行时间
def timer(func):
def deco(*args, **kwargs):
t1 = time.time()
func()
print('running time:%s' % (time.time() - t1))
return deco
@login
def fun1():
time.sleep(3)
print('here is fun1')
@login
def fun2():
time.sleep(3)
print('here is fun2')
@login
def fun3():
time.sleep(3)
print('here is fun3')
fun1()
fun2()
fun3()
浙公网安备 33010602011771号