最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 如何理解python的修饰器

    正文概述    2020-10-17   266

    python的修饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,修饰器的返回值是一个函数对象。

    如何理解python的修饰器

    装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

    功能

    我们首先从一个简单的例子说起,这个例子是stackflow上的一个问题,如何通过使用如下的代码实现输出<b><i>Hello</i></b>:

    @makebold  @makeitalic  def say():  
       return "Hello"

    先看一下答案:

    def makebold(fn):  
        def wrapped():  
            return "<b>" + fn() + "</b>"  
        return wrapped  
       
    def makeitalic(fn):  
        def wrapped():  
            return "<i>" + fn() + "</i>"  
        return wrapped  
      
    @makebold  
    @makeitalic  
    def hello():  
        return "hello world"  
         print hello()
         #返回 <b><i>hello world</i></b>

    这里的@makebold和@makeitalic似乎给Hello加上了一层包装(or修饰),这就是修饰器最明显的体现。

    从需求谈起

    初期,我写了一个函数

    def foo():  
        print 'in foo()'  foo()

    为了检查这个函数的复杂度(在网络编程中程序的延时还是很重要的),需要测算运算时间,增加了计算时间的功能有了下面的代码:

    import time  
    def foo():  
        start = time.clock()  
        print 'in foo()'  
        end = time.clock()  
        print 'Time Elapsed:', end - start  
       
    foo()

    这里只是写了一个函数,如果我想测量多个函数的延时,由于必须知道start与end,所以必须写在程序的开头与结尾,难道每一个程序都这样复制粘贴么?固然可行,但是,我们可以通过设计模式中将功能与数据部分分离一样,将这个测量时间的函数分离出去,就像C++中我们可以将这个测量时间的函数变为一个类,通过调用这个类,赋予不同的函数来测量不同的函数的运行时长。在python中,由于函数实际上就是对象,所以可以利用类似的方法实现:

    import time  
       
    def foo():  
        print 'in foo()'  
       def timeit(func):  
        start = time.clock()  
        func()  
        end =time.clock()  
        print 'Time Elapsed:', end - start  
       
    timeit(foo)

    这里func()就可以指定函数了,但是如果我不想填这个函数或者这个功能函数并不能修改成类似的形式怎么办?我们需要的是最大限度的少改动:

    import time     
    def foo():      
        print 'in foo()'     
    # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法  
    def timeit(func):            
         # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装      
         def wrapper():          
             start = time.clock()          
             func()          
             end =time.clock()          
             print 'Time Elapsed:', end - start             
     # 将包装后的函数返回      
         return wrapper     
     foo = timeit
     (foo)   
     #可以直接写成@timeit + foo定义,python的"语法糖"foo()
     #在这个代码中,timeit(foo)不是直接产生调用效果,而是返回一个与foo参数列表一致的函数,此时此foo非彼foo!因为此时的foo具有了timeit的功效,简单来说就是能够让你在装饰前后执行代码而无须改变函数本身内容,装饰器是一个函数,而其参数为另外一个函数。
     #一个有趣的"汉堡"让你了解顺序
     #顺序在修饰器还是非常重要的,利用一个代码展示一下:
    def bread(func) :      
        def wrapper() :          
            print "</'''       '''\>"          
            func()          
            print "<\______/>"      
        return wrapper     
    def ingredients(func) :      
        def wrapper() :          
            print "#tomatoes#"          
            func()          
            print "~salad~"      
        return wrapper     
    def sandwich(food="--ham--") :      
        print food     
        sandwich()  
    #输出 : --ham--  sandwich = bread(ingredients(sandwich)) 
     sandwich() 
      #输出:  #</'''       '''\>  
       #tomatoes# 
       # --ham--
       # ~salad~ 
       #<\______/>

    加上语法糖,代码可以更简洁:

    def bread(func) :  
        def wrapper() :  
            print "</'''       '''\>"  
            func()  
            print "<\______/>"  
        return wrapper  
       
    def ingredients(func) :  
        def wrapper() :  
            print "#tomatoes#"  
            func()  
            print "~salad~"  
        return wrapper  
    @bread  
    @ingredients  
    def sandwich(food="--ham--") :  
        print food  
       
    sandwich()

    推荐课程:Python基础(周莫烦)


    起源地下载网 » 如何理解python的修饰器

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元