python之装饰器应用场景

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值