zoukankan      html  css  js  c++  java
  • python中装饰器的原理以及实现,

    python版本 3.6

    1.python的装饰器说白了就是闭包函数的一种应用场景,在运用的时候我们遵循

    #开放封闭原则:对修改封闭,对拓展开放

    2.什么是装饰器

    #装饰他人的器具,本身可以是任意可调用的对象,被装饰者也可以是任意可调用对象
    #装饰器的原则:1.不可修改被装饰对象的源代码,2不修改被装饰对象的调用方式
    #装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能

    3.实现装饰器之前先来了解闭包函数

    #1.闭包函数 => 函数嵌套+函数对象+名称空间与作用域
    #闭:定义是在函数内的函数
    #包:该内部函数需要访问一个名字,该名字是属于外层函数作用域的
    
    #闭包函数实现的基本模板
    
    def outter(xxx):
         def inner()
               xxx
          return inner
    
    #为函数体传参的两个方案
    #1.直接传入参数
    #2.在函数体内部定义变量

    4.装饰器的实现

    #阶段一
    #计算一个函数执行的时间
    
    import time
    def index():
          time.sleep(1)
          print("welcome to my world")
    
    start = time.time()
    index()
    end = time.time()
    print("run time is %s" %(end - start))
    #修改了装饰对象的源代码
    
    #阶段二
    import time
    def index():
          time.sleep(1)
          print("welcome to my world")
    
    def wrapper():
          start = time.time()
          index()
          end = time.time()
          print("run time is %s" %(end - start))
    #修改了装饰对象的调用方式
    
    #阶段三
    import time
    def index():
          time.sleep(1)
          print("welcome to my world")
    
    def wrapper(func):
          start = time.time()
          func()
          end = time.time()
          print("run time is %s" %(end - start))
    wrapper(index)
    #修改了装饰对象的调用方式
    
    #阶段四:
    import time
    
    def index():
        time.sleep(1)
        print('welcome to index page')
    
    def timmer(func):
        # func=最原始那个index的内存地址
        def wrapper():
            start=time.time()
            func()
            stop=time.time()
            print('run time is %s' %(stop - start))
        return wrapper
    #把函数作为参数传进去,返回一个函数再去执行,替换返回的函数名为之前传入的函数 
    index=timmer(index) #index=wrapper的内存地址
    index() #wrapper()
    #这样就没有修改被装饰对象的源代码和调用方式

    5.装饰器语法糖

    #装饰器语法糖
    #在被装饰器对象上方单独一行写:@装饰器的名称
    解释器一旦执行到@装饰器的名字就会执行 原函数名 = 装饰器的名字(正下方的那个函数)
    
    #修订之后的装饰器
    import time
    
    def timmer(func):
        # func=最原始那个index的内存地址
        def wrapper(*args,**kwargs):
            start=time.time()
    res
    =func(*args,**kwargs) stop=time.time() print('run time is %s' %(stop - start)) return res return wrapper @timmer #index=timmer(最原始那个index的内存地址) #index=wrapper的内存地址 def index(): time.sleep(1) print('welcome to index page') index()

    6.完善装饰器

    #装饰器实现函数,其函数对象的变化,其中包括一些内置的方法__name__,__doc__等等,
    #这些都是要在被装饰之后返回同样的name,doc
    下面我们引入一个第三方包 去实现这些功能
    import time
    from functools import wraps
    
    def timmer(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            start=time.time()
            #函数返回值
            res=func(*args,**kwargs)
            stop=time.time()
            print('run time is %s' %(stop - start))
            return res
        # wrapper.__doc__=func.__doc__
        # wrapper.__name__=func.__name__
        return wrapper
    
    # @timmer #index=timmer(最原始那个index的内存地址) #index=wrapper的内存地址
    def index():
        """
        这是一个index函数
        :return:
        """
        time.sleep(1)
        print('welcome to index page')
    #上面的引入的第三方包wraps,调用其装饰器帮我们实现了
        # wrapper.__doc__=func.__doc__
        # wrapper.__name__=func.__name__ 等等这些功能,这样能更好的满足用户的需求

    7.上面实现的装饰器是无参装饰器,有参装饰器更新中…………

  • 相关阅读:
    leetcode 437. 路径总和 III
    leetcode 113. 路径总和 II
    题解 【CF387B】George and Round
    题解 【CF489B】 BerSU Ball
    题解【2.23考试T3】val
    题解【2.23考试T1】div
    题解 【洛谷P4290】 [HAOI2008]玩具取名
    题解 【洛谷P1035】[NOIP2002]级数求和
    题解【洛谷P1046】[NOIP2005] 陶陶摘苹果
    题解【洛谷P1618】 三连击(升级版)
  • 原文地址:https://www.cnblogs.com/zj901203/p/9984028.html
Copyright © 2011-2022 走看看