• Python 装饰器相关知识


    Python 装饰器相关知识

    1. 定义:

      不改变原被装饰的函数的源代码以及调用方式下,为其添加额外的功能

    2. 开放封闭原则:

      • 开放:对代码的拓展是开放的,
      • 封闭:对源码的修改是封闭的,
    3. 装饰器:

      • 完全遵循开放封闭原则。

      • 在不改变原函数代码以及调用方式的前提下,为其增加新的功能。

      • 装饰器本质是一个函数。

      • 标准版装饰器格式,Python有个代码优化,叫语法糖:@+装饰器函数名。

      • 具体实现:装饰器函数放在代码的import语句下面,然后在需要装饰的函数前面加上@装饰器名,下面再调用该被装饰的函数时将执行装饰后的函数,调用方法没有任何改变,参数能够照样传进去,返回值也应该可以原样返回

      • 举例:不完整版,带参数,但没有返回值

        def timer(func):  # func = home
            def inner(*args,**kwargs):
                start_time = time.time()
                func(*args,**kwargs)
                end_time = time.time()
                print(f'此函数的执行效率为{end_time-start_time}')
            return inner
        
        @timer  # home = timer(home)
        def home(name,age):
            time.sleep(3)  # 模拟一下网络延迟以及代码的效率
            print(name,age)
            print(f'欢迎访问{name}主页')
        
        home('太白',18)
        
      • 举例:带参数返回值的装饰器,标准版

        def timer(func):  # func = home
            def inner(*args,**kwargs):
                start_time = time.time()
                ret = func(*args,**kwargs)
                end_time = time.time()
                print(f'此函数的执行效率为{end_time-start_time}')
                return ret
            return inner
        
        @timer  # home = timer(home)
        def home(name,age):
            time.sleep(3)  # 模拟一下网络延迟以及代码的效率
            print(name,age)
            print(f'欢迎访问{name}主页')
            return 666
        
        home('太白',18)
        
      • 标准版的装饰器模板:
        def 装饰器函数名(f):					# f参数用于传入被装饰函数名
            def inner(*args,**kwargs):		#  内层的嵌套函数需要传参
                '''添加被装饰函数执行之前的工作'''
                ret = f(*args,**kwargs)		# 调用被装饰函数,需要接收原函数返回值
                '''添加被装饰函数执行之后的工作'''
                return ret					# 将被装饰函数的返回值给返回出去
            return inner
        
    4. 装饰器的应用:

      • 登录认证,用得比较多,还有各类日志。

        模拟博客园登录,需求:在访问每个功能模块之前必须先验证是否已经登录,没有登录不让访问,如没有账号就注册一个再登录,三次登录不成功就退出整个程序。

        status_dict = {  # 登录用户状态
            'username': None,
            'status': False,
        }
        
        def get_usr_pwd():
            pass
        
        def register():
            pass
        
        def login():  # 登录模块,登录3次不成功则退出
            pass
        
        def auth(f):  # 装饰器模板
            def inner(*args, **kwargs):
                if status_dict['status'] == False:          # 如果登录状态为假,则进入登录模块
                    status_dict['username'],status_dict['status'] = login()         # 调用登录模块并接收登录状态
                    if status_dict['status'] == True:       # 如果登录成功,则运行被装饰函数
                        ret = f(*args, **kwargs)
                else:
                    ret = f(*args, **kwargs)
                return ret
            return inner
        
        @auth   # article=auth(article)
        def article():
            print(f'欢迎{status_dict["username"]},访问文章页面。')
        
        @auth
        def comment():
            print('欢迎访问评论页面')
        
        @auth
        def dariy():
            print(f'欢迎{status_dict["username"]},访问日记页面。')
        
        article()
        comment()
        dariy()
        
  • 相关阅读:
    最简单的UDP程序
    最简单的TCP程序
    一道面试题的分析
    JDK5新特性:可变参数方法
    文件IO流总结
    集合使用的总结
    双列集合Map的嵌套遍历
    集合HashSet的使用
    集合TreeSet的使用
    用LinkedList模拟Stack功能
  • 原文地址:https://www.cnblogs.com/amwkvi/p/14030543.html
Copyright © 2020-2023  润新知