2012-08-01 35 views
0

earlier thread跟進我的問題是如何能夠藉此表達:fn(self,*args, **kwargs並調用它在面向對象的方式這樣self.fn(...)這裏是我的總計劃與失敗線註釋掉:裝飾的方法 - 如何調用在面向對象的方式方法,而不是程序的時尚

def formatHeader(fn): 
    def wrapped(*args, **kwargs): 
     print "here is args prior to extraction - {0}".format(args) 
     if len(args) > 1: 
      self,args = args # remove self from args 
     else: 
      self, args= args[0],() 
     print("Here are the arguments after extraction: {0} {1}".format(self, args)) 
     #return '<div class="page_header">' + self.fn(*args, **kwargs)+'</div>' 
     return '<div class="page_header">' + fn(self,*args, **kwargs)+'</div>' 
    return wrapped  

class MyPage(object): 
    def __init__(self): 
     self.PageName = '' 

    def createPage(self): 
     pageHeader = self.createHeader() 
     return pageHeader 

    def addem(self, a, b): 
     return a + b 

    @formatHeader #<----- decorator 
    def createHeader(self): 
     return "Page Header " + self.PageName 


obj = MyPage() 

print obj.createHeader() 
+0

請修復您的格式。看起來好像不是你所有的代碼都已經進入了代碼塊。 – 2012-08-01 15:37:44

+1

......現在的情況怎麼了?裝飾者適用於功能,他們不關心類,並且在寫一個類時也不應該。 (另外,如果你保持現在的狀態,你的代碼就可以在課堂外使用) – 2012-08-01 15:41:07

回答

3

首先,self在該範圍內不存在。 self是按照約定引用類的實例方法中的當前實例的標籤。其次,裝飾器並不意味着要知道它們包裝的函數的實例(至少默認情況下)。該方法綁定到實例,並且裝飾器對作爲黑盒可調用的綁定方法進行操作。如果你想從裝飾器中訪問實例成員(你不應該這樣做,因爲它實際上會破壞oo),所以你必須將實例傳遞給裝飾器,這意味着將裝飾器封閉在一個閉包中,或者使用自省來從裝飾器代碼中動態發現擁有的實例。

1

問題是你的包裝需要訪問它所應用到的實例的另一個方法,但它不會被傳遞,直到運行時 - 與裝飾器運行時的類定義時間相反)。基本上你需要一個實例特定的方法裝飾器。您可以通過將裝飾器描述爲class method decorator using instance配方中描述的PythonDecoratorLibrary來實現此目的。

這是它應用到你的示例代碼(有一些化妝品變動):

from functools import wraps 

def formatHeader(fn): 

    class Descriptor(object): 
     def __init__(self, fn): 
      self.fn = fn 

     def __get__(self, instance, klass): 
      if instance is None: # Class method was requested 
       return self.make_unbound(klass) # will raise TypeError 
      return self.make_bound(instance) 

     def make_unbound(self, klass): 
      @wraps(self.fn) 
      def wrapped(*args, **kwargs): 
       '''This documentation will vanish :)''' 
       raise TypeError(
        'unbound method {}() must be called with {} instance ' 
        'as first argument (got nothing instead)'.format(
         self.fn.__name__, klass.__name__) 
       ) 
      return wrapped 

     def make_bound(self, instance): 
      @wraps(self.fn) 
      def wrapped(*args, **kwargs): 
       '''This documentation will disapear :)''' 
       return ('<div class="page_header">' + 
         self.fn(instance, *args, **kwargs) + '</div>') 

      # This instance does not need the descriptor anymore, 
      # let it find the wrapped method directly next time: 
      setattr(instance, self.fn.__name__, wrapped) 
      return wrapped 

    return Descriptor(fn) 

class MyPage(object): 
    def __init__(self): 
     self.PageName = '' 

    def createPage(self): 
     pageHeader = self.createHeader() 
     return pageHeader 

    def addem(self, a, b): 
     return a + b 

    @formatHeader #<----- decorator 
    def createHeader(self): 
     return "Page Header " + self.PageName 


obj = MyPage() 

print obj.createHeader() 

注意,self參數嵌套描述符類方法是指描述類的實例,而不是其方法是類包裹(代碼中爲instance)。

相關問題