装饰器(decorator)
(“器”代表的是函数)
定义:本质是函数
组成:高阶函数+嵌套函数 --> 装饰器
作用:用来装饰其他函数 in other words,为其他函数添加附加功能
(eg. 假如程序已上线,如果想新增功能,但是又不能改源代码)
原则:
1.不能修改被装饰的函数的源代码
2.不能修改被装饰的函数的调用方试
Q: 高阶嵌套函数是个什么鬼???
高阶函数:
1.把一个函数当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
import time def bar(): time.sleep(3) print("in the bar") def test1(func): start_time = time.time() func() # run bar() stop_time = time.time() print("the func run time is %s"%(stop_time -start_time)) # 统计的是bar的运行时间 test1(bar) # func = bar 所以可以进行func() 传的内存地址 test1(bar()) # 把bar()的返回值传进去了 传的返回值 # BUT !调用方式变了,不是装饰器
2.返回值中包含函数名(不修改函数的调用方式)
import time def bar(): time.sleep(3) print("in the bar") def test2(func): print(func) # 打印func的内存地址,也就是bar的内存地址 return func # return bar的内存地址 bar = test2(bar) bar() # run bar
嵌套函数:
在一个函数的函数体内用def去申明另一个函数
#嵌套函数 def foo(): print("in the foo") def bar(): # 相当于局部变量,所以不能在外面直接调用bar(),所以要写在里面 print("in the bar") bar() foo() # 这个不是函数的嵌套,这叫函数的调用 def test1(): test2() test1()
EXAMPLE 1
优化(@timmer)
def timer(func): #timer(test1) 把test1的内存地址传给func,func = test1 def deco(): start_time = time.time() func() # run test1 stop_time = time.time() print("the func run time is %s"%(start_time-stop_time)) return deco # 返回这个函数的内存地址 @timer # 这就相当于 test1 = timer(test1) def test1(): time.sleep(3) print("in the test1") @timer def test2(): time.sleep(3) print("in the test2") test1() test2() # 其实调用的是deco这个函数,因为timer(test1)的返回值是deco的内存地址
优化(调用时传入多个参数)
def timer(func): #timer(test1) 把test1的内存地址传给func,func = test1 def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) # run test1 stop_time = time.time() print("the func run time is %s"%(start_time-stop_time)) return deco # 返回这个函数的内存地址 @timer # 这就相当于 test1 = timer(test1) = deco def test1(): time.sleep(1) print("in the test1") @timer # test2 = timer(test2) = deco # test2() = deco() 所以在deco里加args def test2(name,age): print("test2:",name,age,) test1() test2("alex",22)
EXAMPLE 2 !!
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("