11.1装饰器的基本概念
装饰器定义:本质是函数,功能是装饰其它函数(就是为其他函数添加附加功能)
原则:1.不能修改被装饰的函数的源代码
- 不能修改被装饰的函数的调用方式
总结:装饰器对被装饰的函数是完全透明的(被装饰的函数不知道装饰器的存在,而装饰器可装饰函数来实现所需功能)
实现装饰器知识储备:
- 函数即“变量”
- 高阶函数
- 把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加)
- 返回值中包含函数名(不修改函数的调用方式)
- 嵌套函数:在一个函数的函数体内用def定义一个新的函数
高阶函数+嵌套函数》装饰器
函数就是变量,定义一个函数就是把函数体赋值给函数名
示例1:
#!Author:lanhan
#@timmer,其实就是 test1=timmer(test1)
import time
def timmer(func):
def warpper(*args,**kwargs):
start_time=time.time()
func()
stop_time=time.time()
print(‘the func run time is %s‘ %(stop_time-start_time))
return warpper()
@timmer
def test1():
time.sleep(3)
print(‘in the test1‘)
test1
示例2:
#!Author:lanhan
#报错,bar()函数根本找不到函数体
def foo():
print(‘in the foo‘)
bar()
foo()
‘‘‘
def bar():
print(‘in the bar‘)
def foo():
print(‘in the foo‘)
bar()
foo()
‘‘‘
# def foo():
# print(‘in the foo‘)
# bar()
# def bar():
# print(‘in the bar‘)
# foo()
##报错,原因是内存中还没有解释到bar,foo()就执行了
def foo():
print(‘in the foo‘)
bar()
foo()
def bar():
print(‘in the bar‘)
foo()
示例3:
#!Author:lanhan
‘‘‘
#bar函数是源代码,test1装饰bar,但缺点是修改了源代码的调用方式
import time
def bar():
time.sleep(3)
print(‘in the bar‘)
def test1(func):
start_time=time.time()
func() #run bar bar的运行时间
stop_time=time.time()
print("the func run time is %s" %(stop_time-start_time))
test1(bar) #bar=func
#bar() #直接调用不能增加附加功能
‘‘‘
import time
def bar():
time.sleep(3)
print(‘in the bar‘)
def test2(func):
print(func) #新增功能
return func
#print(test2(bar))
bar=test2(bar)
bar() #b.返回值中包含函数名(不修改函数的调用方式),bar是内存地址,相当于门牌号,bar()则是调用函数
#print(t)
#t()
示例4:
#!Author:lanhan
#嵌套函数
def foo():
print(‘in the foo‘)
def bar(): #函数即变量,所以可看成是局部变量,拥有局部变量特性。只在局部能被调用
print(‘in the bar‘)
bar()
foo()
示例5:
import time
def timer(func): ##func=test1
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 ##返回deco内存地址
@timer ##test1=timer(test1)
def test1():
time.sleep(3)
print(‘in the test1‘)
@timer ##test2=timer(test2) = deco test2() =deco()
def test2():
time.sleep(3)
print(‘in the test2‘)
‘‘‘
test1=deco(test1)
test1()
test2=deco(test2)
test2()
‘‘‘
#test1=(timer(test1)) #test1=deco的内存地址
test1() #执行deco函数
#test2=(timer(test1)) #test1=deco的内存地址
test2() #执行deco函数
示例6:
#同个装饰器装饰不同个数的参数的函数
import time
def timer(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" %(stop_time-start_time))
return deco ##返回deco内存地址
@timer ##test1=timer(test1)
def test1():
time.sleep(3)
print(‘in the test1‘)
@timer ##test2=timer(test2) = deco test2() =deco()
def test2(name,age):
print("test2:",name,age)
#test1=(timer(test1)) #test1=deco的内存地址
test1() #执行deco函数
#test2=(timer(test1)) #test1=deco的内存地址
test2("lanhan",22) #执行deco函数
示例7:
#!Author:lanhan
#装饰器传参数,实现同个装饰器实现多个不同功能
import time
user,passwd = ‘lanhan‘,‘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 paswd authentication\033[0m")
res = func(*args,**kwargs)
print("---after authentication")
return res ##把"from home"返回
else:
exit("\033[32;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()
#home()
print(home())
bbs()