zoukankan      html  css  js  c++  java
  • python基础 day14 装饰器

    一、装饰器的认识

    • 在不改变原被装饰的函数的源代码以及调用方式情况下,为其添加新的功能。
    • 完全遵循开放封闭原则
    • 装饰器的本质就是闭包
    # 标准版装饰器
    def wrapper(f):  # f 是传入的被装饰的函数名
        def inner(*args, **kwargs):  # 传入被装饰的函数的参数
            '''添加额外功能,执行被装饰函数之前的操作'''
            ret = f(*args, **kwargs)  # 执行被装饰的函数,并获取被装饰函数的返回值
            '''添加额外功能,执行被装饰函数之后的操作'''
            return ret
        return inner
    
    @wrapper
    def func():
        pass
    
    func()
    
    • 装饰器实现功能的分析

    1.我们给这个测试函数加一个装饰器,计算执行这个函数需要的时间

    # step1:
    import time
    def test_func():  # 这是需要被装饰的函数
        time.sleep(1)
        print('this is a test function')
    
    # 我们给这个测试函数加一个装饰器,计算执行这个函数需要的时间
    def wrapper(f):
        start_time = time.time()
        f()
        end_time = time.time()
        print(end_time - start_time)
    
    wrapper(test_func)
    
    # 但是装饰器要符合开放封闭原则,并且被装饰函数的调用方式也改变了
    

    2.使用闭包,实现开放封闭原则

    # step2:
    import time
    def test_func():  # 这是需要被装饰的函数
        time.sleep(1)
        print('this is a test function')
    
    # 使用闭包,实现开放封闭原则
    def wrapper(f):
        # f = wrapper(test_func)  # f就是一个闭包中的自由变量
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            print(end_time - start_time)
        return inner
    # wrapper(test_func)()  # 想要执行被装饰函数,就要执行inner(),而wrapper(test_func)返回的就是inner
    test_func = wrapper(test_func)  # 使用赋值,让函数执行方式不改变
    test_func()  # 实际上就是执行inner()
    

    3.python 进行了优化,这里可以这样写

    # step3:
    import time
    # 使用闭包,实现开放封闭原则
    def wrapper(f):
        def inner():
            start_time = time.time()
            f()
            end_time = time.time()
            print(end_time - start_time)
        return inner
    
    @wrapper  # 相当于test_func = wrapper(test_func)
    def test_func():  # 这是需要被装饰的函数
        time.sleep(1)
        print('this is a test function')
    
    test_func()  # 实际上就是执行inner()
    

    4.当被装饰函数有返回值时,要在inner函数中返回被装饰函数的返回值

    # step4:被装饰函数有返回值时,要在inner函数中返回被装饰函数的返回值
    import time
    # 使用闭包,实现开放封闭原则
    def wrapper(f):
        # f = test_func
        def inner():
            start_time = time.time()
            ret = f()
            end_time = time.time()
            print(end_time - start_time)
            return ret
        return inner
    
    @wrapper  # 相当于test_func = wrapper(test_func)
    def test_func():  # 这是需要被装饰的函数
        time.sleep(1)
        print('this is a test function')
        return 'aloha'
    
    result = test_func()  # 实际上就是执行inner()
    print(result)
    

    5.当被装饰函数需要传入参数时,要在inner函数中传入对应的参数

    # step5:被装饰函数需要传入参数时,要在inner函数中传入对应的参数
    
    import time
    # 使用闭包,实现开放封闭原则
    def wrapper(f):
        # f = test_func
        def inner(*args, **kwargs):
            start_time = time.time()
            ret = f(*args, **kwargs)
            end_time = time.time()
            print(end_time - start_time)
            return ret
        return inner
    
    @wrapper  # 相当于test_func = wrapper(test_func)
    def test_func(name, age):  # 这是需要被装饰的函数
        time.sleep(1)
        print('this is a test function')
        info = f'我叫{name}, 今年{age}'
        return 'aloha', info
    
    result = test_func('jason', 18)  # 实际上就是执行inner()
    print(result)
    

    二、装饰器的应用

    登录认证系统

    # 简单模拟博客园登录系统
    # 在访问文章,照片,文件之前,需要登录账号密码
    login_status = {'username': '', 'status': False}
    
    
    def get_user_password():  # 获取账号密码文件
        user_dic = dict()
        with open('user.txt', 'r', encoding='utf-8') as f1:
            for line in f1:
                line_list = line.strip().split('|')
                user_dic.update({line_list[0]: line_list[1]})
        return user_dic
    
    
    def login():  # 用户登录(三次机会)
        user_dic = get_user_password()
        count = 0
        while count < 3:
            username = input("请输入账户名:").strip()
            password = input("请输入密码:").strip()
            if username in user_dic and user_dic[username] == password:
                print(f'{username}你好,欢迎登录博客园')
                login_status['username'] = username
                login_status['status'] = True
                break
            else:
                print('账号或密码错误')
            count += 1
    
    
    def auth(f):  # 登录认证的装饰器
        def inner(*args, **kwargs):
            if login_status['status']:
                ret = f(*args, **kwargs)
                return ret
            else:
                login()
                ret = f(*args, **kwargs)
                return ret
        return inner
    
    
    @auth
    def article():
        print('欢迎访问文章页面')
    
    
    @auth
    def photo():
        print('欢迎访问照片页面')
    
    
    @auth
    def file():
        print('欢迎访问文件页面')
    
    
    article()
    photo()
    file()
    
  • 相关阅读:
    WebStorm2020.3.0及以下安装激活方法
    CSS随堂笔记【狂神说JAVA】
    HTML随堂笔记【狂神说JAVA】
    JAVA语言基础随堂笔记
    js 常用类和方法
    js 数组
    js 对象和函数
    js 基础语法
    JavaScript 简介
    PS基础
  • 原文地址:https://www.cnblogs.com/west-yang/p/12634862.html
Copyright © 2011-2022 走看看