装饰器
定义:本质是函数,装饰其它函数,为其它函数添加附加功能。
原则:
1.不能修改被装饰的函数的源代码。
2.不能修改被装饰的函数的调用方式。
装饰器对被装饰的函数是完全透明的。
#统计函数运行时间的装饰器 import time def timmer(func): def warpper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print("The func run time is %s " %(stop_time-start_time)) return warpper @timmer def test1(): time.sleep(1) print("in the test1") test1() #运行结果 #in the test1 #The func run time is 1.000936508178711
装饰圈 = 高阶函数 + 嵌套函数
1.函数即变量
变量都是存在内存中,如x=1,以房间和门牌号为例,门牌号为x,房间为1。
加一个变量y且y=x 即门牌号为y,房间为1
解释器内存回收机制即门牌号没有了就回收内存。
函数在内存中存放方式:门牌号为函数名,房间为函数体。
2.高阶函数
A 把一个函数名当作实参传给另外一个函数。
在不修改被装饰函数源代码的情况下为其添加功能
#例 统计函数运行时间 import time def bar(): time.sleep(1) print("In the bar") def test(func): start_time = time.time() func() #相当于 bar() stop_time = time.time() print("The func run time is %s " %(stop_time - start_time)) test(bar) #bar其实就是一个函数的内存地址 # In the bar # The func run time is 1.0003819465637207
B 返回值中包含函数名。
不修改函数的调用方式
import time def bar(): time.sleep(1) print("In the bar") def test(func): print(func) return func test(bar) #得到bar函数的内存地址 内存地址+括号可以运行函数 bar = test(bar) bar() #run bar
3.嵌套函数
#嵌套函数 在一个函数里面用def 定义一个函数 def foo(): print("In the foo") def bar(): print("In the bar") bar() foo() #局部作用域与全局作用域的访问顺序 x = 0 def grandpa(): x = 1 def dad(): x = 2 def son(): x = 3 print(x) son() dad() grandpa()
装饰器
#用装饰器实现函数运行时间 #装饰器分步实现 step1 改变了调用方式 import time def test1(): time.sleep(1) print("In the test1") def test2(): time.sleep(1) print("In the test2") def deco(func): start_time = time.time() func() stop_time = time.time() print("The func run time is %s" %(stop_time-start_time)) deco(test1) deco(test2) #step2 不改变源代码不改变调用方式 import time def test1(): time.sleep(1) print("In the test1") def test2(): time.sleep(1) print("In the test2") def timmer(func): def deco(): start_time = time.time() func() #run test1 stop_time = time.time() print("The func run time is %s" %(stop_time-start_time)) return deco test1 = timmer(test1) test2 = timmer(test2) test1() test2() #step3 在python中使用语法糖 @装饰器名 #在需要添加新功能的函数前面加上语法糖 #可以用debug查看逻辑变化及顺序 import time def timmer(func): def deco(): start_time = time.time() func() #run test1 stop_time = time.time() print("The func run time is %s" %(stop_time-start_time)) return deco @timmer #语法糖 def test1(): time.sleep(1) print("In the test1") @timmer def test2(): time.sleep(1) print("In the test2") test1() test2() #有参数的函数被装饰 import time def timmer(func): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) #run test1 stop_time = time.time() print("The func run time is %s" %(stop_time-start_time)) return deco @timmer def test1(): time.sleep(1) print("In the test1") @timmer def test2(name): time.sleep(1) print("In the test2" ,name) test1() test2('test') #用户登陆认证装饰器 part1 user,passwd = 'test','123' def auth(func): def wrapper(*args,**kwargs): username = input("Usernmae:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed\033[0m") res = func(*args,**kwargs) return res else: exit("\033[31;1mInvalid username or passwd\033[0m") return wrapper @auth def index(): print("Welcome to index page") @auth def home(): print("Welcome to home page") return "from home" @auth def bbs(): print("Welcome to bbs page") index() home() print(home()) bbs() #区分本地和ldap登陆 user,passwd = 'test','123' def auth(auth_type): def outer_wrapper(func): def wrapper(*args,**kwargs): if auth_type == "local": username = input("Usernmae:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[32;1mUser has passed\033[0m") res = func(*args,**kwargs) return res else: exit("\033[31;1mInvalid username or passwd\033[0m") elif auth_type == "ldap": print("The ldap") return wrapper return outer_wrapper def index(): print("Welcome to index page") @auth(auth_type="local") def home(): print("Welcome to home page") return "from home" @auth(auth_type="ldap") def bbs(): print("Welcome to bbs page") index() home() print(home()) bbs()