• Python之装饰器


    定义:装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
    应用场景:比如插入日志、性能测试、事务处理、缓存、权限校验等场景。

     一、装饰器的形成过程

    1、自定义装饰器

    #简单装饰器
    import time  
    def timmer(f):
        def inner():
            start_time = time.time()
            time.sleep(0.1)
            f()
            end_time = time.time()
            print('----> 执行效率:%s' %(end_time - start_time))
        return inner
    #需要引用装饰器的函数
    def func():
        print('嘻嘻更健康')
      
    #引用装饰器 
    func = timmer(func)     #inner
    func()                  #inner()
    #输出结果
    嘻嘻更健康
    ----> 执行效率:0.10022902488708496
    

    2、装饰器的语法糖

    #装饰的语法糖@
    def timmer(f):  #装饰器
        def inner():
            f()
        return inner
     
    @timmer     #@timmer 相当于 func = timmer(func)
    def func():     #要引用装器的函数
        print('嘻嘻更健康')
    func()      #func() = inner()    调用装饰器
    #输出结果
    嘻嘻更健康
    

    3、带参数函数的装饰器

    # 函数带参数的装饰器
    def timmer(f):
        #此处传入动态参数
        def inner(*args,**kwargs):
            f(*args,**kwargs)
        return inner
      
    @timmer         # func = timmer(func)
    def func(a):    # 第一个函数,参数a
        print('%s嘻嘻更健康'%a)
      
    @timmer         # func1 = timmer(func1)
    def func1(a,b): # 第二个函数,参数a、b
        print('%s和%s嘻嘻更健康' %(a,b))
      
    func('张三')
    func1('张三','李四')
    #输出结果
    张三嘻嘻更健康
    张三和李四嘻嘻更健康
    

    4、带返回值函数的装饰器

    # 函数带有返回值的装饰器
    def timmer(f):
        def inner(*args,**kwargs):
            ret = f(*args,**kwargs)  
            return ret			# 将函数的返回值返回
        return inner
     
    @timmer     # func = timmer(func)
    def func():
        return '函数的返回值'
    #执行函数
    print(func())
    #输出结果
    函数的返回值
    

    5、带参数的装饰器

    #带参数的装饰器
    flag = True
    def outer(flag):
        def timer(func):
            def inner(*args,**kwargs):
                if flag==True:
                    print('''执行函数之前要做的''')
                ret = func(*args,**kwargs)
                if flag==False:
                    print('''执行函数之后要做的''')
                return ret
            return inner
        return timer
    
    @outer(flag)
    def func():
        print('这是执行函数')
    #调用执行函数
    func()
    #输出结果
    执行函数之前要做的
    这是执行函数
    

    6、函数带有多个装饰器

    #装饰器1
    def wrapper1(func):
        def inner():
            print('wrapper1, before func')
            func()
            print('wrapper1, after func')
        return inner
    #装饰器2
    def wrapper2(func):
        def inner():
            print('wrapper2, before func')
            func()
            print('wrapper2, after func')
        return inner
    
    @wrapper2
    @wrapper1
    def func():
        print('执行函数')
    
    func()
    #输出结果
    wrapper2 ,before func
    wrapper1 ,before func
    执行函数
    wrapper1 ,after func
    wrapper2 ,after func

    7、查看函数信息的相关方法

    #正常情况下查看
    def index():
        '''函数的注释'''
        print('from index')
    
    print(index.__doc__)    #查看函数注释的方法
    print(index.__name__)   #查看函数名的方法
    #输出结果
    函数的注释
    index
    #查看带有装饰器的函数
    from functools import wraps
    
    def decorate(func):
        @wraps(func)    #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    
    @decorate
    def index():
        '''函数的注释'''
        print('from index')
    
    print(index.__doc__)
    print(index.__name__)
    #输出结果
    函数的注释
    index
    

    总结:通用装饰器公式

    #固定公式1
    def wrapper(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            ret = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return ret
        return inner
    
    #固定公式2
    from functools import wraps
    def deco(func):
        @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper
    
    @wrapper
    def func1():
        print("函数func1")
    func1()             #函数func1
    
    @deco
    def func2():
        print("函数func2")
    func2()             #函数func2
    

    二、装饰器的开放封闭原则

    1、对扩展是开放的
      为什么要对扩展开放呢?
      我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
    2、对修改是封闭的
      为什么要对修改封闭呢?
      就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

     

  • 相关阅读:
    [易学易懂系列|rustlang语言|零基础|快速入门|(18)|use关键词]
    [易学易懂系列|rustlang语言|零基础|快速入门|(17)|装箱crates]
    [易学易懂系列|rustlang语言|零基础|快速入门|(16)|代码组织与模块化]
    区块链行业访谈:《创世访谈录》
    波卡简介
    [易学易懂系列|rustlang语言|零基础|快速入门|(15)|Unit Testing单元测试]
    GIT分布式代码管理系统
    jenkins介绍及部署tomcat环境、部署Maven项目及密码忘记修改
    Docker安装、命令详情、层级架构、docker服务启动失败解决方法
    ELK日志分析系统部署
  • 原文地址:https://www.cnblogs.com/lioushell/p/8417894.html
Copyright © 2020-2023  润新知