<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python--- 裝飾器

          共 3435字,需瀏覽 7分鐘

           ·

          2021-02-18 18:30

          作者:Vamei 出處:http://www.cnblogs.com/vamei

          裝飾器(decorator)是一種高級(jí)Python語法。裝飾器可以對(duì)一個(gè)函數(shù)、方法或者類進(jìn)行加工。在Python中,我們有多種方法對(duì)函數(shù)和類進(jìn)行加工,比如在Python閉包中,我們見到函數(shù)對(duì)象作為某一個(gè)函數(shù)的返回結(jié)果。相對(duì)于其它方式,裝飾器語法簡(jiǎn)單,代碼可讀性高。因此,裝飾器在Python項(xiàng)目中有廣泛的應(yīng)用。

          裝飾器最早在Python 2.5中出現(xiàn),它最初被用于加工函數(shù)和方法這樣的可調(diào)用對(duì)象(callable object,這樣的對(duì)象定義有__call__方法)。在Python 2.6以及之后的Python版本中,裝飾器被進(jìn)一步用于加工類。

          ?

          裝飾函數(shù)和方法

          我們先定義兩個(gè)簡(jiǎn)單的數(shù)學(xué)函數(shù),一個(gè)用來計(jì)算平方和,一個(gè)用來計(jì)算平方差:

          # get square sumdef square_sum(a, b):    return a**2 + b**2
          # get square diffdef square_diff(a, b): return a**2 - b**2print(square_sum(3, 4))print(square_diff(3, 4))

          在擁有了基本的數(shù)學(xué)功能之后,我們可能想為函數(shù)增加其它的功能,比如打印輸入。我們可以改寫函數(shù)來實(shí)現(xiàn)這一點(diǎn):

          # modify: print input
          # get square sumdef square_sum(a, b): print("intput:", a, b) return a**2 + b**2
          # get square diffdef square_diff(a, b): print("input", a, b) return a**2 - b**2print(square_sum(3, 4))print(square_diff(3, 4))

          我們修改了函數(shù)的定義,為函數(shù)增加了功能。

          ?

          現(xiàn)在,我們使用裝飾器來實(shí)現(xiàn)上述修改:

          def decorator(F):    def new_F(a, b):        print("input", a, b)        return F(a, b)    return new_F
          # get square sum@decoratordef square_sum(a, b): return a**2 + b**2
          # get square diff@decoratordef square_diff(a, b): return a**2 - b**2
          print(square_sum(3, 4))print(square_diff(3, 4))

          裝飾器可以用def的形式定義,如上面代碼中的decorator。裝飾器接收一個(gè)可調(diào)用對(duì)象作為輸入?yún)?shù),并返回一個(gè)新的可調(diào)用對(duì)象。裝飾器新建了一個(gè)可調(diào)用對(duì)象,也就是上面的new_F。new_F中,我們增加了打印的功能,并通過調(diào)用F(a, b)來實(shí)現(xiàn)原有函數(shù)的功能。

          定義好裝飾器后,我們就可以通過@語法使用了。在函數(shù)square_sum和square_diff定義之前調(diào)用@decorator,我們實(shí)際上將square_sum或square_diff傳遞給decorator,并將decorator返回的新的可調(diào)用對(duì)象賦給原來的函數(shù)名(square_sum或square_diff)。所以,當(dāng)我們調(diào)用square_sum(3, 4)的時(shí)候,就相當(dāng)于:

          square_sum = decorator(square_sum)square_sum(3, 4)

          我們知道,Python中的變量名和對(duì)象是分離的。變量名可以指向任意一個(gè)對(duì)象。從本質(zhì)上,裝飾器起到的就是這樣一個(gè)重新指向變量名的作用(name binding),讓同一個(gè)變量名指向一個(gè)新返回的可調(diào)用對(duì)象,從而達(dá)到修改可調(diào)用對(duì)象的目的。

          與加工函數(shù)類似,我們可以使用裝飾器加工類的方法。

          ?

          如果我們有其他的類似函數(shù),我們可以繼續(xù)調(diào)用decorator來修飾函數(shù),而不用重復(fù)修改函數(shù)或者增加新的封裝。這樣,我們就提高了程序的可重復(fù)利用性,并增加了程序的可讀性。

          ?

          含參的裝飾器

          在上面的裝飾器調(diào)用中,比如@decorator,該裝飾器默認(rèn)它后面的函數(shù)是唯一的參數(shù)。裝飾器的語法允許我們調(diào)用decorator時(shí),提供其它參數(shù),比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。

          # a new wrapper layerdef pre_str(pre=''):    # old decorator    def decorator(F):        def new_F(a, b):            print(pre + "input", a, b)            return F(a, b)        return new_F    return decorator
          # get square sum@pre_str('^_^')def square_sum(a, b): return a**2 + b**2
          # get square diff@pre_str('T_T')def square_diff(a, b): return a**2 - b**2
          print(square_sum(3, 4))print(square_diff(3, 4))

          上面的pre_str是允許參數(shù)的裝飾器。它實(shí)際上是對(duì)原有裝飾器的一個(gè)函數(shù)封裝,并返回一個(gè)裝飾器。我們可以將它理解為一個(gè)含有環(huán)境參量的閉包。當(dāng)我們使用@pre_str('^_^')調(diào)用的時(shí)候,Python能夠發(fā)現(xiàn)這一層的封裝,并把參數(shù)傳遞到裝飾器的環(huán)境中。該調(diào)用相當(dāng)于:

          square_sum?=?pre_str('^_^')?(square_sum)

          裝飾類

          在上面的例子中,裝飾器接收一個(gè)函數(shù),并返回一個(gè)函數(shù),從而起到加工函數(shù)的效果。在Python 2.6以后,裝飾器被拓展到類。一個(gè)裝飾器可以接收一個(gè)類,并返回一個(gè)類,從而起到加工類的效果。

          def decorator(aClass):    class newClass:        def __init__(self, age):            self.total_display   = 0            self.wrapped         = aClass(age)        def display(self):            self.total_display += 1            print("total display", self.total_display)            self.wrapped.display()    return newClass
          @decoratorclass Bird: def __init__(self, age): self.age = age def display(self): print("My age is",self.age)
          eagleLord = Bird(5)for i in range(3): eagleLord.display()

          在decorator中,我們返回了一個(gè)新類newClass。在新類中,我們記錄了原來類生成的對(duì)象(self.wrapped),并附加了新的屬性total_display,用于記錄調(diào)用display的次數(shù)。我們也同時(shí)更改了display方法。

          通過修改,我們的Bird類可以顯示調(diào)用display的次數(shù)了。

          ?

          總結(jié)

          裝飾器的核心作用是name binding。這種語法是Python多編程范式的又一個(gè)體現(xiàn)。大部分Python用戶都不怎么需要定義裝飾器,但有可能會(huì)使用裝飾器。鑒于裝飾器在Python項(xiàng)目中的廣泛使用,了解這一語法是非常有益的。

          瀏覽 57
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花成人视频在线 | 12—13女人毛片毛片 | 性欧美tube | 免费一级特黄录像 | 大香蕉性伊 |