https://blog.youkuaiyun.com/weixin_45912307/article/details/115450640
1. 装饰器定义:满足闭包条件,装饰器的入参是一个函数,其返回值也是一个函数对象;
- 满足闭包的三个条件:
- 在外部函数中定义了内部函数
- 外层函数返回内层嵌套函数名
- 内层嵌套函数有引用外层非全局变量
2. 作用:在不更改原功能函数代码,并且不改变调用方法的情况下为原函数添加新的功能;
3. 应用场景(实例)
应用1:登录/支付验证
import sys
import time
# 1. 登录操作
isLogin = False
def login():
while True:
username = 'admin'
password = '123456'
user = input("请输入用户名:")
pwd = input("请输入密码:")
if str(user) == username and str(pwd) == password:
return True
else:
return False
# 2. 支付验证
def payment_verification(func):
# 1. 如果登录成功则调用pay
while True:
def wrapper(*args, **kwargs):
global isLogin
if isLogin:
func(*args, **kwargs)
# 2. 否则调用login
else:
print("没有登录,请先进行账号登录")
n = 0
while n < 3:
isLogin = login()
if isLogin:
func(*args, **kwargs)
break
else:
print('第{}次登录失败'.format(n + 1))
n += 1
if n == 3:
sys.exit("输入三次失败,账号已被锁定,请联系管理员")
return wrapper
# 3. 支付操作
@payment_verification
def pay(money):
print('正在付款,付款金额是:{}'.format(money))
print('付款中....')
time.sleep(3)
print('付款成功')
if __name__ == '__main__':
pay(8000)
应用2:时间统计模块
def time_wrapper(func):
def run_time(*args,**kwargs):
star_time = time.time()
func(*args,**kwargs)
end_time = time.time()
print("run time:{:.10f}".format(end_time-star_time))
return run_time
@time_wrapper
@decorator
def t1():
li = [i for i in range(1000)]
return li
t = t1()
应用3:单例模式
def single(cls):
__isinstance = {}
def wrapper(*args,**kwargs):
if cls in __isinstance:
return __isinstance[cls]
else:
__isinstance[cls] = cls(*args,**kwargs)
return __isinstance[cls]
return wrapper
@single
class CustomClass:
pass
cc1 = CustomClass()
cc2 = CustomClass()
print(cc1 is cc2)
应用4:类通用装饰器,既可以装饰函数也可以装饰类,既可以装饰有参数的,又可以装饰无参数的
class GenerateClass:
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
print("generator inner function")
self.func(*args,**kwargs)
@GenerateClass
def testDemo(): # 没有实例化的类也可以被call
print("original function")
testDemo()
应用5:日志模块
from functools import wraps
def log_generator(func):
@wraps(func)
def logging_wrapper(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return logging_wrapper
@log_generator
def testcase001(x):
"""Do some math."""
return x * x
result = testcase001(4)
应用6:数据库打开关闭
import pymysql
class OperateMysqlDb():
def openClose(fun):
def run(self, sql=None, logging=None, *args, **kwargs):
# 创建数据库连接
global data
db = pymysql.connect(*args,**kwargs)
# 创建游标
cursor = db.cursor()
try:
# 运行sql语句
self.cursor.execute(fun(self, sql))
# 得到返回值
data = cursor.fetchall()
# 提交事务
db.commit()
except Exception as e:
# 如果出现错误,回滚事务
db.rollback()
# 打印报错信息
logging.error("run str(fun errorMessage{}:".format(e))
finally:
# 关闭游标和数据库连接
cursor.close()
db.close()
try:
# 返回sql执行信息
return data
except:
logging.error('没有得到返回值,请检查代码,该信息出现在OperateMysqlDb类中的装饰器方法')
return run
@openClose
def runSql(self, sql=None):
return sql