Welcome to kimi's blog

装饰器的推导过程

装饰器的推导过程

装饰器

​ 引入

​ 软件的设计应该遵循开放封闭原则,即是对扩展是开放的,而对修改是封闭的,软件包含的所有功能的源代码以及调用方式,都应该避免修改,否则一旦改错,则极有可能产生连锁反应,最终导致程序崩溃。对于新上线的软件,我们可能要对客户的新需求或者变化,对程序提供扩展的可能性,这就用到了装饰器

装饰器简介

  1. 概念

    在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能

  2. 本质

    并不是一门新的技术,而是由函数参数、名称空间、函数名多种用法、闭包函数组合到一起的结果

  3. 口诀

    对修改封闭、对扩展开放

  4. 储备知识

    时间相关操作

    import time
    # print(time.time())  #  时间戳(距离1970-01-01 00:00:00所经历的秒数)

    time.sleep(2)
    print('五点就到饭点了')


    count = 0
    # 循环之前先获取时间戳
    start_time = time.time()
    while count<1000:
        print('赏心悦目')
        count += 10
    end_time = time.time()
    print('循环消耗的时间:',end_time - start_time)

  1. 应用场景

    用于有切面需求的场景,比如插入日志、性能测试、事务处理、缓存、权限校验等应用场景

装饰器推导过程

    import time

    def func():
        time.sleep(3)
        print('花花')
    def home():
        time.sleep(1)
        print('润玥')

  
"""  1.直接在调用func函数的前后添加代码     """

    start_time = time.time()
    func()  # 花花
    end_time = time.time()
    print('函数func的执行时间为>>:',end_time - start_time)  # 函数func的执行时间为>>: 3.01410174369812


""" 2.func调用的地方较多,代码不可能反复拷贝>>>>:相同的代码需要在不同的位置反复执行>>>:函数"""
    def get_time():
        start_time = time.time()
        func()
        end_time = time.time()
        print('函数func的执行时间为>>:', end_time - start_time)   # 函数func的执行时间为>>: 3.0112600326538086
    get_time()


""" 3.函数体代码写死了,只能统计func()的执行时间,如何才能做到统计更多的函数运行时间,直接传参变换统计的函数"""
    def get_time(xxx):
        start_time = time.time()
        xxx()
        end_time = time.time()
        print('函数func的执行时间为>>:', end_time - start_time)
    get_time(func)
    get_time(home)


"""4.虽然实现了一定的兼容性,但是并不符合装饰器的特征,第一种转参不写,只能考虑闭包"""
    def get_time(xxx):
        # xxx = index
        def outer():
            start_time = time.time()
            xxx()
            end_time = time.time()
            print('函数func的执行时间为>>:', end_time - start_time)
        return outer

    res = get_time(func)
    res()
    res1 = get_time(home)
    res1()


""" 5.调用方式还是不对,如何变形>>>:变量名赋值绑定(***********)"""
    def outer(xxx):
        def get_time():
            start_time = time.time()
            xxx()
            end_time = time.time()
        return get_time

    res = outer(func)  # 赋值符号的左边是一个变量名,可以随意命名
    res1 =outer(func)
    kiki = outer(func)
    func =outer(func)
    home = outer(home)
    home()


"""6.上述装饰器只能装饰无参函数,兼容性太差"""
    def func1(a):
        time.sleep(1)
        print('艾玖', a)

    def func2(a, b):
        time.sleep(2)
        print('福宝', a, b)

    def func3():
        time.sleep(3)
        print('和叶')

    func1(123) #  艾玖 123
    def outer(xxx):
        def get_time(a, b):
            start_time = time.time()
            xxx(a, b)
            end_time = time.time()
            print('函数func的执行时间为>>:', end_time - start_time)
        return  get_time

    func2 = outer(func2)
    func2(120,119)  # 福宝 120 119
    func1 = outer(func1)
    func1(120)  # 艾玖 123
    func3 = outer(func3)
    func3()  # get_time() missing 2 required positional arguments: 'a' and 'b'


"""7.被装饰的函数不知道有没有参数以及几个参数,如何兼容"""
    def func1(a):
        time.sleep(1)
        print('艾玖', a)

    def func2(a, b):
        time.sleep(2)
        print('福宝', a, b)

    def outer(xxx):
        def get_time(*args,**kwargs):
            start_time = time.time()
            xxx(*args,**kwargs)
            end_time = time.time()
            print('函数的执行时间为>>>:',end_time - start_time)
        return get_time

    func1 = outer(func1)
    func1(120)  # 艾玖 120

    func2 = outer(func2)
    func2(120,119)  # 福宝 120 119



"""8.如果被装饰的函数有返回值"""

    def func1(a):
        time.sleep(1)
        print('艾玖', a)
        return 'func1'

    def func2(a, b):
        time.sleep(2)
        print('福宝', a, b)
        return 'func2'

    def outer(xxx):
        def get_time(*args,**kwargs):
            start_time = time.time()
            res = xxx(*args,**kwargs)
            end_time = time.time()
            print('函数的执行时间为>>>:',end_time - start_time)
            return res
        return get_time

    func1 = outer(func1)
    res = func1(120)  # 艾玖 120
    print(res)  # func1

    func2 = outer(func2)
    res = func2(119, 120)  # 福宝 119 120
    print(res)    # func2


解读步骤如图
image

装饰器模板

重点掌握:

def outer(func):
    def inner(*args,**kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func(*args,**kwargs)
        print('执行被装饰对象之后可以做的额外的操作')
        return res
    return inner

作业

  1. 编写一个用户认证装饰器
    函数:register login transfer withdraw
    基本要求
    执行每个函数的时候必须先校验身份 eg: jason 123
    拔高练习(有点难度)
    执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
    提示:全局变量 记录当前用户是否认证
def outer(func):
    def inner(*args,**kwargs):
        username = input('please input your name>>>:').strip()
        password = input('please input your password').strip()
        if username == 'kiki' and password == '123':
            print('登录成功')
        else:
            print('用户名或者密码错误')
            return
        res = func(*args,**kwargs)
        return res
    return inner

@outer
def register():
    print("注册功能")

@outer
def login():
    print("登录功能")

@outer
def transfer():
    print("转账功能")

@outer
def withdraw():

    print("提现功能")

dict1 ={'1':register,
        '2':login,
        '3':transfer,
        '4':withdraw
        }

while True:
    print(f"""
    1.注册功能
    2.登录功能
    3.转账功能
    4.体现功能
    """)
    choice = input('请输入您的想要的编号>>>:')
    if choice in dict1:
        dict1.get(choice)()
    else:
        print('输入的编号有误')
		
		```
完整版
def outer(func):
    def inner(*args,**kwargs):
        global is_login
        # 先判断全局名称空间中的变量名is_login绑定的值是否为True
        if is_login :
            res = func(*args, **kwargs)
            return res
        username = input('please input your name>>>:').strip()
        password = input('please input your password').strip()
        if username == 'kiki' and password == '123':
            #将全局名称空间中记录用户登录状态的数据值该为True
            is_login = True
            res = func(*args, **kwargs)
            return res
        else:
            print('用户名或者密码错误')
    return inner

@outer
def register():
    print("注册功能")

@outer
def login():
    print("登录功能")

@outer
def transfer():
    print("转账功能")

@outer
def withdraw():
    print("提现功能")


dict1 ={'1':register,
        '2':login,
        '3':transfer,
        '4':withdraw
        }

while True:
    print(f"""
    1.注册功能
    2.登录功能
    3.转账功能
    4.体现功能
    """)
    choice = input('请输入您的想要的编号>>>:')
    if choice in dict1:
        dict1.get(choice)()
    else:
        print('输入的编号有误')
posted @ 2022-10-11 20:24  魔女宅急便  阅读(69)  评论(0)    收藏  举报
Title