亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

python 裝飾函數 和 閉包 基礎總結。

系統 2263 0

一、 裝飾函數

(1)概念:

裝飾器本質上是一個 Python 函數或類,它可以讓其他函數或類在不需要做任何代碼修改的前提下 增加額外功能 ,裝飾器的返回值也是一個 函數/類對象 。它經常用于有切面需求的場景,比如:插入日志、性能測試、事務處理、緩存、權限校驗等場景,裝飾器是解決這類問題的絕佳設計。有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼到裝飾器中并繼續重用。概括的講,裝飾器的作用就是 為已經存在的對象添加額外的功能

使用方法:

  1. 先定義一個裝飾器(帽子)
  2. 再定義你的業務函數或者類(人)
  3. 最后把這裝飾器(帽子)扣在這個函數(人)頭上

(2)實例:

  1. 日志打印器
            
              
                # 這是裝飾器函數,參數 func 是被裝飾的函數
              
              
                def
              
              
                logger
              
              
                (
              
              func
              
                )
              
              
                :
              
              
                def
              
              
                wrapper
              
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                '主人,我準備開始執行:{} 函數了:'
              
              
                .
              
              
                format
              
              
                (
              
              func
              
                .
              
              __name__
              
                )
              
              
                )
              
              
                # 真正執行的是這行。
              
              
        func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
                print
              
              
                (
              
              
                '主人,我執行完啦。'
              
              
                )
              
              
                return
              
               wrapper
@logger  
              
                # =》 add = logger(add)
              
              
                def
              
              
                add
              
              
                (
              
              x
              
                ,
              
               y
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                '{} + {} = {}'
              
              
                .
              
              
                format
              
              
                (
              
              x
              
                ,
              
               y
              
                ,
              
               x
              
                +
              
              y
              
                )
              
              
                )
              
            
          

執行:
在這里插入圖片描述
2. 時間計時器

            
              
                # 這是裝飾函數
              
              
                def
              
              
                timer
              
              
                (
              
              func
              
                )
              
              
                :
              
              
                def
              
              
                wrapper
              
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
                :
              
              
        t1
              
                =
              
              time
              
                .
              
              time
              
                (
              
              
                )
              
              
                # 這是函數真正執行的地方
              
              
        func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
        t2
              
                =
              
              time
              
                .
              
              time
              
                (
              
              
                )
              
              
                # 計算下時長
              
              
        cost_time 
              
                =
              
               t2
              
                -
              
              t1 
        
              
                print
              
              
                (
              
              
                "花費時間:{}秒"
              
              
                .
              
              
                format
              
              
                (
              
              cost_time
              
                )
              
              
                )
              
              
                return
              
               wrapper

              
                import
              
               time

@timer

              
                def
              
              
                want_sleep
              
              
                (
              
              sleep_time
              
                )
              
              
                :
              
              
    time
              
                .
              
              sleep
              
                (
              
              sleep_time
              
                )
              
              

want_sleep
              
                (
              
              
                10
              
              
                )
              
              
                #花費時間:10.000298261642456秒
              
            
          
  1. 帶參數的函數裝飾器
            
              
                def
              
              
                say_hello
              
              
                (
              
              contry
              
                )
              
              
                :
              
              
                def
              
              
                wrapper
              
              
                (
              
              func
              
                )
              
              
                :
              
              
                def
              
              
                deco
              
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              
                :
              
              
                if
              
               contry 
              
                ==
              
              
                "china"
              
              
                :
              
              
                print
              
              
                (
              
              
                "你好!"
              
              
                )
              
              
                elif
              
               contry 
              
                ==
              
              
                "america"
              
              
                :
              
              
                print
              
              
                (
              
              
                'hello.'
              
              
                )
              
              
                else
              
              
                :
              
              
                return
              
              
                # 真正執行函數的地方
              
              
            func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              
                return
              
               deco
    
              
                return
              
               wrapper


              
                # 小明,中國人
              
              
@say_hello
              
                (
              
              
                "china"
              
              
                )
              
              
                def
              
              
                xiaoming
              
              
                (
              
              
                )
              
              
                :
              
              
                pass
              
              
                # jack,美國人
              
              
@say_hello
              
                (
              
              
                "america"
              
              
                )
              
              
                def
              
              
                jack
              
              
                (
              
              
                )
              
              
                :
              
              
                pass
              
            
          

python 裝飾函數 和 閉包 基礎總結。_第1張圖片
4. 不帶參數的類裝飾器
基于類裝飾器的實現,必須實現 call 和 __init__兩個內置函數。
init :接收被裝飾函數
call :實現裝飾邏輯。

            
              
                class
              
              
                logger
              
              
                (
              
              
                object
              
              
                )
              
              
                :
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               func
              
                )
              
              
                :
              
              
        self
              
                .
              
              func 
              
                =
              
               func

    
              
                def
              
              
                __call__
              
              
                (
              
              self
              
                ,
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "[INFO]: the function {func}() is running..."
              
              \
            
              
                .
              
              
                format
              
              
                (
              
              func
              
                =
              
              self
              
                .
              
              func
              
                .
              
              __name__
              
                )
              
              
                )
              
              
                return
              
               self
              
                .
              
              func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              

@logger

              
                def
              
              
                say
              
              
                (
              
              something
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "say {}!"
              
              
                .
              
              
                format
              
              
                (
              
              something
              
                )
              
              
                )
              
              

say
              
                (
              
              
                "hello"
              
              
                )
              
              
                #[INFO]: the function say() is running...
              
              
                #say hello!
              
            
          
  1. 帶參數的類裝飾器
    上面不帶參數的例子,你發現沒有,只能打印INFO級別的日志,正常情況下,我們還需要打印DEBUG WARNING等級別的日志。這就需要給類裝飾器傳入參數,給這個函數指定級別了。

帶參數和不帶參數的類裝飾器有很大的不同。

init :不再接收被裝飾函數,而是接收傳入參數。
call :接收被裝飾函數,實現裝飾邏輯。

            
              
                class
              
              
                logger
              
              
                (
              
              
                object
              
              
                )
              
              
                :
              
              
                def
              
              
                __init__
              
              
                (
              
              self
              
                ,
              
               level
              
                =
              
              
                'INFO'
              
              
                )
              
              
                :
              
              
        self
              
                .
              
              level 
              
                =
              
               level

    
              
                def
              
              
                __call__
              
              
                (
              
              self
              
                ,
              
               func
              
                )
              
              
                :
              
              
                # 接受函數
              
              
                def
              
              
                wrapper
              
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "[{level}]: the function {func}() is running..."
              
              \
                
              
                .
              
              
                format
              
              
                (
              
              level
              
                =
              
              self
              
                .
              
              level
              
                ,
              
               func
              
                =
              
              func
              
                .
              
              __name__
              
                )
              
              
                )
              
              
            func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kwargs
              
                )
              
              
                return
              
               wrapper  
              
                #返回函數
              
              

@logger
              
                (
              
              level
              
                =
              
              
                'WARNING'
              
              
                )
              
              
                def
              
              
                say
              
              
                (
              
              something
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                "say {}!"
              
              
                .
              
              
                format
              
              
                (
              
              something
              
                )
              
              
                )
              
              

say
              
                (
              
              
                "hello"
              
              
                )
              
              
                #[WARNING]: the function say() is running...
              
              
                #say hello!
              
            
          
  1. 內置裝飾器:property
            
            
          
  1. 如果 decorator本身需要傳入參數 ,那就需要編寫一個返回decorator的高階函數。(即再嵌套一個decorator函數):
            
              
                def
              
              
                log
              
              
                (
              
              text
              
                )
              
              
                :
              
              
                def
              
              
                decorator
              
              
                (
              
              func
              
                )
              
              
                :
              
              
        @functools
              
                .
              
              wraps
              
                (
              
              func
              
                )
              
              
                #把原始函數的__name__等屬性復制到wrapper()函數中
              
              
                def
              
              
                wrapper
              
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                '%s %s():'
              
              
                %
              
              
                (
              
              text
              
                ,
              
               func
              
                .
              
              __name__
              
                )
              
              
                )
              
              
                return
              
               func
              
                (
              
              
                *
              
              args
              
                ,
              
              
                **
              
              kw
              
                )
              
              
                return
              
               wrapper
    
              
                return
              
               decorator

@log
              
                (
              
              
                'execute'
              
              
                )
              
              
                #now = log('execute')(now)
              
              
                def
              
              
                now
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                '2015-3-25'
              
              
                )
              
              

now
              
                (
              
              
                )
              
              
                #execute now():
              
              
                #2015-3-25
              
            
          

首先執行log(‘execute’),返回的是decorator函數,再調用返回的函數,參數是now函數,返回值最終是wrapper函數。

二、閉包

(1)概念:

在一個內部函數中,對外部作用域的變量進行引用,(并且一般外部函數的返回值為內部函數),那么內部函數就被認為是閉包。
維基百科上的解釋是:

              
                在計算機科學中,閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,
是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,
即使已經離開了創造它的環境也不例外。
所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。

              
            

在這里插入圖片描述

add訪問了外部函數start的變量,并且函數返回值為add函數(python可以 返回函數
python 裝飾函數 和 閉包 基礎總結。_第2張圖片
閉包,顧名思義,就是一個封閉的包裹,里面包裹著 自由變量 ,就像在類里面定義的屬性值一樣,自由變量的可見范圍隨同包裹,哪里可以訪問到這個包裹,哪里就可以訪問到這個自由變量。

再通過Python的語言介紹一下,一個閉包就是你調用了一個函數A,這個函數A返回了一個函數B給你。這個返回的函數B就叫做閉包。你在調用函數A的時候傳遞的參數就是自由變量(當函數A的生命周期結束之后,自由變量依然存在,因為它被閉包引用了,所以不會被回收。)。

(2)常見問題

  1. 閉包無法修改 外部函數 局部變量 (即add函數無法修改start函數定義的變量)

  2. 閉包使得 局部變量 函數外 被訪問成為可能

  3. 閉包避免了使用全局變量

  4. 閉包允許將函數與其所操作的某些數據(環境)關連起來。

  5. 裝飾器就是一種的閉包的應用,只不過其傳遞的是 函數

  6. 閉包的最大特點是可以將 父函數的變量與內部函數綁定 ,并返回綁定變量后的函數(也即閉包)。(類似類)

  7. python循環中不包含域的概念。

python 裝飾函數 和 閉包 基礎總結。_第3張圖片
loop在python中是沒有域的概念的,flist在向列表中添加func的時候,并沒有保存i的值,而是當執行f(2)的時候才去取,這時候循環已經結束,i的值是2,所以結果都是4。

解決辦法:
在func外面再定義一個makefun函數,func形成閉包。 python 裝飾函數 和 閉包 基礎總結。_第4張圖片
參考:
https://foofish.net/python-closure.html
https://zhuanlan.zhihu.com/p/22229197


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日本欧美视频在线 | 91九色蝌蚪在线 | 久久精品一区二区三区资源网 | 香蕉视频在线免费播放 | 国产欧美日韩中文字幕 | 亚洲第一伊人 | 在线播放免费一级毛片欧美 | 一道本不卡免费视频 | 啊用力嗯快国产在线观看 | 欧美精品专区免费观看 | 性短视频在线观看免费不卡流畅 | 中国美女一级a毛片录像在线 | 伊在人亚洲香蕉精品播放 | 久久视频在线看 | 成年激情网 | 亚洲小视频在线播放 | 亚洲已满18点击进入在线观看 | 99精品国产第一福利网站 | 成人国产欧美精品一区二区 | 国产精片| 色八a级在线观看 | 国产成人亚洲日本精品 | 日本精品视频在线观看 | 久久桃花| 一级国产视频 | 天天干天天干天天干天天干天天干 | 久久夜色精品 | 欧美激情(一区二区三区) | 日韩免费一区二区 | 欧美国产激情二区三区 | 久久精品中文字幕免费 | 亚洲精品日本一区二区在线 | 久草视频免费 | 色综合天天综合网看在线影院 | 婷婷的久久五月综合先锋影音 | 人成在线免费视频 | 亚洲欧美强伦一区二区另类 | 国产亚洲精品久久yy5099 | 欧美一级毛片免费大全 | a视频网站 | 久久久久在线观看 |