15 Python学习之装饰器
装饰器
装饰器:在不改变源函数的代码及调用方式的前提下,为其增加新的功能,装饰器就是一个函数,他的本质是闭包
装饰器开放封闭的原则:
开放:对代码的扩展开放
封闭:对源码的修改是封闭的
被装饰函数无参数,无返回值
例1:
import time
def timer(func):
def inner():
start_time = time.time()
func()
end_time = time.time()
print(f'装饰器打印执行时间为:{round(end_time - start_time, 5)}')
return inner # 闭包,返回内层函数的引用
# show_info = timer(show_info)第一个show_info是一个新的变量,第二个show_info的函数名,@timer是show_info = timer(show_info)的简写,官方叫做语法糖
@timer
def show_info():
print(f"我的姓名是:张三")
time.sleep(2)
show_info()
运行结果:
我的姓名是:张三
装饰器打印执行时间为:2.00051
被装饰函数有返回值
被装饰函数有返回值,那么在设计装饰器的时候,就应该有变量进行接收,然后再将该返回值返回给调用者
例1:
import time
def timer(func):
def inner():
start_time = time.time()
inner_ret = func() # 调用原函数并接受返回值
end_time = time.time()
print(f'装饰器打印执行时间为:{round(end_time - start_time, 5)}')
return inner_ret # 将调用原函数的返回值返回给调用者
return inner # 闭包,返回内层函数的引用
@timer # show_info = timer(show_info)第一个show_info是一个新的变量,第二个show_info的函数名,@timer是show_info = timer(show_info)的简写,官方叫做语法糖
def show_info():
print(f"我的姓名是:张三")
time.sleep(2)
return 'show_info函数的返回值'
ret = show_info() # ret接受的是inner的返回值inner_ret
print(ret)
我的姓名是:张三
装饰器打印执行时间为:2.00168
show_info函数的返回值
被装饰函数有参数
被装饰函数有参数,由于实际调用的时候,掉的是闭包中的内部函数,所以内部函数相应的也要设计成跟原函数一样的带参数
例1:
import time
def timer(func):
def inner(name): # 设计时需要添加参数
start_time = time.time()
inner_ret = func(name) # 调用原函数indxe,传入参数并接受返回值
end_time = time.time()
print(f'装饰器打印执行时间为:{round(end_time - start_time, 5)}')
return inner_ret # 将调用原函数的返回值返回给调用者
return inner # 闭包,返回内层函数的引用
@timer # show_info = timer(show_info)第一个show_info是一个新的变量,第二个show_info的函数名,@timer是show_info= timer(show_info)的简写,官方叫做语法糖
def show_info(name):
print(f"我的姓名是:{name}")
time.sleep(2)
return 'show_info函数的返回值'
ret = show_info('张三') # 相当于ret = inner('张三')
print(ret)
我的姓名是:张三
装饰器打印执行时间为:2.00031
show_info函数的返回值
标准装饰器
由于被装饰函数的参数个数不确定,所以我们在设计装饰器时,内部函数的参数个数就无法确定,因此要设计成不定长的形式
例1:
import time
def timer(func):
def inner(*args, **kwargs): # 设计时需要添加参数
start_time = time.time()
inner_ret = func(*args, **kwargs) # 调用原函数indxe,传入参数并接受返回值
end_time = time.time()
print(f'装饰器打印执行时间为:{round(end_time - start_time, 5)}')
return inner_ret # 将调用原函数的返回值返回给调用者
return inner # 闭包,返回内层函数的引用
@timer # show_info = timer(show_info)第一个show_info是一个新的变量,第二个show_info的函数名,@timer是show_info= timer(show_info)的简写,官方叫做语法糖
def show_info(name, age):
print(f"我的姓名是:{name}, 今年{age}岁")
time.sleep(2)
return 'show_info函数的返回值'
ret = show_info('张三', 25)
print(ret)
我的姓名是:张三, 今年25岁
装饰器打印执行时间为:2.0017
show_info函数的返回值
特别注意
在标准装饰器中,def inner(*args, **kwargs):
中的 *
在函数 定义 的时候是将传入函数的参数聚合成一个元素,在 调用函数inner_ret = func(*args, **kwargs)
的时候 *
的作用是将一个可迭代的对象进行打散,即将变量 args或kwargs
打散,拆分成一个个要传入的实参
标准装饰器模板:
def decorator(real_func_name):
def inner(*args, **kwwargs):
'''调用装饰器访问函数前要执行的操作'''
ret = real_func_name(*args, **kwwargs)
'''调用装饰器访问函数后要执行的操作'''
return ret
return inner
装饰器的应用
装饰器一般用于登录验证和日志
例1:
def login():
name = input('请输入用户名:')
pwd = input('请输入密码:')
login_status['name'] = name
if pwd == '123456':
login_status['status'] = True
return 1
else:
return 0
login_status = {
'name': None,
'status': False
}
def decorator(func_name):
def inner(*args, **kwargs):
if login_status['status']:
ret = func_name(*args, **kwargs)
return ret
else:
ret = login()
if ret:
ret = func_name()
return ret
else:
print('登录失败')
return inner
@decorator
def index():
print("index页面")
@decorator
def logger():
print("logger页面")
# 只有登录成功后才会执行函数,并打印信息
index()
logger()
请输入用户名:张三
请输入密码:123456
index页面
logger页面
上一篇: Java调用shell脚本
下一篇: Tomcat基本配置详解