<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                由于函數也是一個對象,而且函數對象可以被賦值給變量,所以,通過變量也能調用該函數。 ~~~ >>> def now(): ... print('2015-3-25') ... >>> f = now >>> f() 2015-3-25 ~~~ 函數對象有一個`__name__`屬性,可以拿到函數的名字: ~~~ >>> now.__name__ 'now' >>> f.__name__ 'now' ~~~ 現在,假設我們要增強`now()`函數的功能,比如,在函數調用前后自動打印日志,但又不希望修改`now()`函數的定義,這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。 本質上,decorator就是一個返回函數的高階函數。所以,我們要定義一個能打印日志的decorator,可以定義如下: ~~~ def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper ~~~ 觀察上面的`log`,因為它是一個decorator,所以接受一個函數作為參數,并返回一個函數。我們要借助Python的@語法,把decorator置于函數的定義處: ~~~ @log def now(): print('2015-3-25') ~~~ 調用`now()`函數,不僅會運行`now()`函數本身,還會在運行`now()`函數前打印一行日志: ~~~ >>> now() call now(): 2015-3-25 ~~~ 把`@log`放到`now()`函數的定義處,相當于執行了語句: ~~~ now = log(now) ~~~ 由于`log()`是一個decorator,返回一個函數,所以,原來的`now()`函數仍然存在,只是現在同名的`now`變量指向了新的函數,于是調用`now()`將執行新函數,即在`log()`函數中返回的`wrapper()`函數。 `wrapper()`函數的參數定義是`(*args, **kw)`,因此,`wrapper()`函數可以接受任意參數的調用。在`wrapper()`函數內,首先打印日志,再緊接著調用原始函數。 如果decorator本身需要傳入參數,那就需要編寫一個返回decorator的高階函數,寫出來會更復雜。比如,要自定義log的文本: ~~~ def log(text): def decorator(func): def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator ~~~ 這個3層嵌套的decorator用法如下: ~~~ @log('execute') def now(): print('2015-3-25') ~~~ 執行結果如下: ~~~ >>> now() execute now(): 2015-3-25 ~~~ 和兩層嵌套的decorator相比,3層嵌套的效果是這樣的: ~~~ >>> now = log('execute')(now) ~~~ 我們來剖析上面的語句,首先執行`log('execute')`,返回的是`decorator`函數,再調用返回的函數,參數是`now`函數,返回值最終是`wrapper`函數。 以上兩種decorator的定義都沒有問題,但還差最后一步。因為我們講了函數也是對象,它有`__name__`等屬性,但你去看經過decorator裝飾之后的函數,它們的`__name__`已經從原來的`'now'`變成了`'wrapper'`: ~~~ >>> now.__name__ 'wrapper' ~~~ 因為返回的那個`wrapper()`函數名字就是`'wrapper'`,所以,需要把原始函數的`__name__`等屬性復制到`wrapper()`函數中,否則,有些依賴函數簽名的代碼執行就會出錯。 不需要編寫`wrapper.__name__ = func.__name__`這樣的代碼,Python內置的`functools.wraps`就是干這個事的,所以,一個完整的decorator的寫法如下: ~~~ import functools def log(func): @functools.wraps(func) def wrapper(*args, **kw): print('call %s():' % func.__name__) return func(*args, **kw) return wrapper ~~~ 或者針對帶參數的decorator: ~~~ import functools def log(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator ~~~ `import functools`是導入`functools`模塊。模塊的概念稍候講解。現在,只需記住在定義`wrapper()`的前面加上`@functools.wraps(func)`即可。 ### 小結 在面向對象(OOP)的設計模式中,decorator被稱為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實現,而Python除了能支持OOP的decorator外,直接從語法層次支持decorator。Python的decorator可以用函數實現,也可以用類實現。 decorator可以增強函數的功能,定義起來雖然有點復雜,但使用起來非常靈活和方便。 請編寫一個decorator,能在函數調用的前后打印出`'begin call'`和`'end call'`的日志。 再思考一下能否寫出一個`@log`的decorator,使它既支持: ~~~ @log def f(): pass ~~~ 又支持: ~~~ @log('execute') def f(): pass ~~~ ### 參考源碼 [decorator.py](https://github.com/michaelliao/learn-python3/blob/master/samples/functional/decorator.py)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看