<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      Python深入05 裝飾器

      作者:Vamei 出處:http://www.rzrgm.cn/vamei 歡迎轉載,也請保留這段聲明。謝謝!

       

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

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

       

      裝飾函數和方法

      我們先定義兩個簡單的數學函數,一個用來計算平方和,一個用來計算平方差:

      # get square sum
      def square_sum(a, b):
          return a**2 + b**2
      
      # get square diff
      def square_diff(a, b):
          return a**2 - b**2

      print(square_sum(3, 4))
      print(square_diff(3, 4))

      在擁有了基本的數學功能之后,我們可能想為函數增加其它的功能,比如打印輸入。我們可以改寫函數來實現這一點:

      # modify: print input
      
      # get square sum
      def square_sum(a, b):
          print("intput:", a, b)
          return a**2 + b**2
      
      # get square diff
      def square_diff(a, b):
          print("input", a, b)
          return a**2 - b**2

      print(square_sum(3, 4))
      print(square_diff(3, 4))

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

       

      現在,我們使用裝飾器來實現上述修改:

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

      裝飾器可以用def的形式定義,如上面代碼中的decorator。裝飾器接收一個可調用對象作為輸入參數,并返回一個新的可調用對象。裝飾器新建了一個可調用對象,也就是上面的new_F。new_F中,我們增加了打印的功能,并通過調用F(a, b)來實現原有函數的功能。

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

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

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

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

       

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

       

      含參的裝飾器

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

      # a new wrapper layer
      def 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是允許參數的裝飾器。它實際上是對原有裝飾器的一個函數封裝,并返回一個裝飾器。我們可以將它理解為一個含有環境參量的閉包。當我們使用@pre_str('^_^')調用的時候,Python能夠發現這一層的封裝,并把參數傳遞到裝飾器的環境中。該調用相當于:

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

       

      裝飾類

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

      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
      
      @decorator
      class 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中,我們返回了一個新類newClass。在新類中,我們記錄了原來類生成的對象(self.wrapped),并附加了新的屬性total_display,用于記錄調用display的次數。我們也同時更改了display方法。

      通過修改,我們的Bird類可以顯示調用display的次數了。

       

      總結

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

       

      歡迎繼續閱讀“Python快速教程

       

      posted @ 2013-02-16 17:18  Vamei  閱讀(41541)  評論(33)    收藏  舉報
      主站蜘蛛池模板: 樱花草视频www日本韩国| 亚洲国产精品国自拍av| 加勒比无码av中文字幕 | 极品无码国模国产在线观看| 久久经精品久久精品免费观看| 通州区| 欧美三级中文字幕在线观看| 国产精品日日摸夜夜添夜夜添2021 | 人人妻人人爽人人添夜夜欢视频| 99亚洲男女激情在线观看| 亚洲色无码播放亚洲成av| 瑞金市| 欧美综合区自拍亚洲综合绿色| 精品久久人人妻人人做精品| A级毛片100部免费看| 天天狠天天透天天伊人| 久久国产热这里只有精品| 亚洲成人av在线资源| 精品人妻av综合一区二区| 日韩有码中文在线观看| 国产成人高清精品亚洲| 免费国产一级特黄aa大片在线| 国产69精品久久久久99尤物| 国产精品最新免费视频| 欧美颜射内射中出口爆在线| 国产精品久久露脸蜜臀| 成人国产精品免费网站| 99久久国产精品无码| 精品国产制服丝袜高跟| 国产极品尤物粉嫩在线观看| 国产超碰无码最新上传| 无套内谢少妇毛片在线| 18禁免费无码无遮挡网站| 中文字幕在线精品国产| yw尤物av无码国产在线观看| 妓女妓女一区二区三区在线观看| 69天堂人成无码免费视频| 国产成人免费ā片在线观看| 成人爽a毛片免费| 亚洲一区二区中文字幕| 欧美日韩国产码高清|