zoukankan      html  css  js  c++  java
  • 装饰器

    装饰器

    一、无参装饰器

    1.1 什么是装饰器?

    装饰器,器指的是工具,二而程序中的函数就是具备某一功能的工具,所以装饰器指的是为被装饰器对象(函数)添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能

    装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B,

    需要注意的是:

    • 装饰器本身其实就是可以任意调用的对象

    • 被装饰的对象也可以是任意可调用的对象

      def A():
           """装饰器"""
           pass
      
      def B():
           """被装饰的对象"""
          pass
      
      B()
      

    1.2 为什么要用装饰器?

    如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。

    装饰器的实现必须遵循两大原则:

    1. 不修改被装饰对象的源代码
    2. 不修改被装饰对象的调用方式

    装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

    1.3 如何使用装饰器

    def index():
         """被装饰的函数"""
        print('hello, index')
        
    index()
    

    对上面函数实现:

    1.打印函数运行的时间

    1.1 改变了函数体代码,没改变调用方式

    import time
    def index():
        start = time.time()
        print("hello, index")
        time.sleep(1)
        end = time.time()
        print(end - start)
    index()
    

    1.2 没改变调用方式,也没改变源码,但是不通用

    import time
    def index():
        print("hello, index")
        
    start = time.time()
    index()
    time.sleep(1)
    end = time.time()
    
    print(end - start)
    

    2.装饰器

    检测index的运行的时间,但是不能改变index的调用方式,以及index的源码

    def deco(func): # func = 真正的index
        """装饰器函数"""
        
        def inner():
            start = time.time()
            func() # 真正的index()
            time.sleep(1)
            end = time.time()
            print(ent - start)
        return inner
    
    def index():
        """被装饰的函数"""
        print("hello, index")
        
     # 实现index函数调用   
    index = deco(index) # index = inner
    index() # f1()
    
    

    二、装饰器语法糖

    在被装饰函数正上方,并且是单独一行写上@装饰器名

    def deco(func): # func = 真正的index
        """装饰器函数"""
        
        def inner():
            start = time.time()
            func() # 真正的index()
            time.sleep(1)
            end = time.time()
            print(ent - start)
        return inner
    
    def index():
        """被装饰的函数"""
        print("hello, index")
    @deco
    index() 
    

    三、装饰器模板

    def outter(func):
        def inner(*args, **kwagrs): 
            """
            args: 被装饰的位置形参
            kwargs: 被装饰的默认形参/关键字实参
            """
            res = func(*args, **kwagrs)
            return res
        return inner
    
    
    def deco(func):
        """装饰器"""
        def inner(*args, **kwargs): # inner是未来要运行的函数
            res = func(*args, **kwargs) # func实际调用的函数
            return res
        return inner
    
    @deco
    def index(x, a=12):
        """被装饰的对象"""
        
        print('x:',x,)
        print("a:", a)
        print('hello index')
        
        return index
    
    
    res = index()
    print(res)
    

    实现一个用户登录装饰器。

    def login(func):
        def ingfunc(*args, **kwargs):
    
            username = input("请输入用户名:")
            userpwd = input("请输入密码:")
    
            if username == 'randy' and userpwd:
                print("登录成功")
    
                res = func(*args, **kwargs)
            else:
                print('失败')
    
            return res
    
        return ingfunc
    @time_count
    @login  # 多个装饰器从下到上执行
    def shopping():
        print('shoppoing')
    
    
    shopping()
    

    四、三层装饰器(有参装饰器)

    # 三层装饰器
    def sanceng(engine):
        def outter(func):
            def wrapper(*args, **kwargs):
                # 加功能
                print(engine)
                res = func(*args, **kwargs) # func被装的函数
                return res
            return wrapper
        return outter
    
    @sanceng('file')
    def shopping()
    	print("shopping")
    
    # 判断账号密码来自于哪个地方
    #三层装饰器: 给双层装饰器加参数
    def auth(engine):
        def login(func):
            def inner(*args, **kwargs):
                # 登录功能
                if engine == 'file':
                    username = input('usrename:')
                    pwd = input('pwd:')
                    if username == 'nick' and pwd == '123':
                        print('登录成功')
                        res = func(*args, **kwargs)  # shopping()                    return res
                    else:
                        print('登录失败')
               elif engine == 'db':
                    print('账号密码来自于数据库,非法请求')
            return inner
        return login
    
    @auth('db')
    def shopping():
        print('shopping')
    
    
    login = auth('db')  # login = login
    shopping = login(shopping)  # shopping = inner
    shopping() # inner()
    
    # 叠加多个装饰器
    # 1. 加载顺序(outter函数的调用顺序):自下而上
    # 2. 执行顺序(wrapper函数的执行顺序):自上而下
    

    五、三层装饰器模板

    def wrapper(param=None):
        def outter(func):
            def innter(*args, **kwargs):
                print(param)
                res = func(*args, **kwargs)
                return res
    
            return innter
    
        return outter
    

    六、总结

    1. 装饰作用:为被装饰器装饰的对象添加额外功能,好处在于,不改变被装饰器对象的源代码和调用方式;
    2. 两层装饰器模板
    from functools import wraps
    
    def outter(func):
        @wraps(func)
        def innter(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return innter
    
    1. 三层装饰器模板
    
    def wrapper(param=None):
    
        def outter(func):
            def innter(*args, **kwargs):
                res = func(*args, **kwargs)
                return res
            
            return innter
        
        return outter
    
    在当下的阶段,必将由程序员来主导,甚至比以往更甚。
  • 相关阅读:
    多路径下使用ASMLIB创建ASM磁盘
    linux7.4开启hugepages
    Oracle 12CR2 RAC 升级
    深度思考比勤奋更重要(转)
    Oracle最大保护模式是有延迟的
    mysql主从安装简记
    Socket 监控服务器运行状态
    12C Sharding 学习安装
    惊喜与局限并存,12c Sharding内测报告抢先看!
    Oracle 12c 分片(Sharding)技术
  • 原文地址:https://www.cnblogs.com/randysun/p/11341112.html
Copyright © 2011-2022 走看看