装饰器
1.装饰器:器代表函数的意思
装饰器的本质就是函数,也是用def定义的。
功能是用来装饰其他函数的,就是为其他函数添加附加功能。
2.原则:
(1)不能修改被装饰的函数的源代码
(2)不能修改被装饰的函数的调用方式
(3)装饰器对被装饰的函数来说是透明的,感知不到装饰器的存在,该怎么运行就怎么运行
3.实现装饰器的知识储备:
(1)函数即变量
def func():
函数体
func是存储函数体的一个变量
定义一个函数就是相当于把函数体赋值给了一个函数名。
解释器
当内存区域的数据没有引用时会被删掉
(2)高阶函数
满足下面两个条件之一为高阶函数:
a:把一个函数名当作实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
import time
def bar():
time.sleep(3)
print('in the bar')
def te1(func):
start_time=time.time()
func() #run bar 实现了装饰器的功能,不修改bar函数原代码同时增加了打印运行时间的功能
#但是它修改了bar的调用方式,te1(bar),而原来为bar()
stop_time=time.time()
print("the func run time is %s" %(stop_time-start_time))
te1(bar)
bar()
b:返回值中包含函数名(不修改函数的调用方式)
import time
def bar():
time.sleep(3)
print('in the bar')
def te2(func):
print(func)
return func
bar=te2(bar) #把之前的bar覆盖掉了
bar() #调用函数的方式没有改变
(3)嵌套函数
在函数中再定义函数
def foo():
print('in the foo')
def bar(): #bar为局部变量,在函数体外不能调用,具有局部变量的特性
print('in the bar')
bar()
foo()
#bar()会调用失败
4.高阶函数+嵌套函数 = 装饰器
import time
#这是一个可以任意传参的装饰器
def timer(func): #timer(test1) func=te1
def deco(*args,**kwargs):
start_time=time.time()
func(*args,**kwargs) #run te1()
stop_time = time.time()
print("the func run time is %s" %(stop_time-start_time))
return deco
@timer #相当于te1=timer(te1) 这个@timer加到哪个函数的前面,就是哪个函数的装饰器
def te1():
time.sleep(1)
print('in the test1')
@timer # te2 = timer(te2) = deco te2(name) =deco(name)
def te2(name,age):
print("te2:",name,age)
te1()
te2("cay",22)
5.装饰器终极版(多层嵌套时返回值以及传参的疑惑)
import time
user,passwd = 'cay','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()