2017-09-26 94 views
0

所以在python的docutils包中有一個類(Image),它有一個方法(align)。據我所知,它的方法以自身作爲第一個參數,除非它們被裝飾爲@classmethod或@staticmethod,但是align不會。相關代碼複製如下(full code here)。python類中的實例方法和靜態方法

class Image(Directive): 

    def align(argument): 
     # This is not callable as self.align. We cannot make it a 
     # staticmethod because we're saving an unbound method in 
     # option_spec below. 
     return directives.choice(argument, Image.align_values) 

我使用這個代碼,作爲我自己的目的的基地,我曾經嘗試都給人對齊自我論證,並把它變成一個靜態方法(更改名稱,以免與自己發生衝突後, .align),但兩種方法都有錯誤。到底是怎麼回事?

+0

你能提供什麼錯誤嗎? – MaLiN2223

+0

with @staticmethod:'staticmethod'對象不可調用。添加'self':align_option()缺少1個必需的位置參數:'arg'。 – vorpal

+0

實際上這是記錄:「這不能作爲self.align調用,我們不能將它作爲靜態方法,因爲我們在下面的option_spec中保存了一個未綁定的方法。」 –

回答

2

沒有要求命名第一個參數self;那只是一個慣例。在下面的代碼

i = Image() 
i.align() 

align方法將參照到對象i參數argument被調用。

下面的函數將相同的行爲:

def align(self): 
    return directives.choice(self, Image.align_values) 

(簡單地用更常見selfargument替換)。


在上下文中,功能align從未旨在是的方法;作者似乎只是定義了一個函數來存儲在options_spec字典中。可以在不刪除函數引用保存後的名稱污染類的命名空間已經取得了預期的效果:

option_spec = {'alt': directives.unchanged, 
       'height': directives.length_or_unitless, 
       'width': directives.length_or_percentage_or_unitless, 
       'scale': directives.percentage, 
       'align': align, 
       'name': directives.unchanged, 
       'target': directives.unchanged_required, 
       'class': directives.class_option} 
del align 

或免收def聲明—這是一個非常簡單的功能—和使用lambda表達式來創建功能。

option_spec = {'alt': directives.unchanged, 
       'height': directives.length_or_unitless, 
       'width': directives.length_or_percentage_or_unitless, 
       'scale': directives.percentage, 
       'align': lambda x: directives.choice(x, Image.align_values) 
       'name': directives.unchanged, 
       'target': directives.unchanged_required, 
       'class': directives.class_option} 
+0

這就是我的想法,但至少就我理解的代碼而言,通過什麼來傳遞對齊IS是一個真實的參數(具體來說,無論用戶輸入的是對齊選項),而不僅僅是自己使用不同的名稱。 directives.choice函數檢查參數1是否是tupple參數2的成員。因爲Image.align_values是字符串的指針,這意味着參數1必須是字符串而不是類Image的實例。 – vorpal

+1

啊,它在技術上是一種實例方法,*但它永遠不會被用作這種方法。相反,函數存儲在一個'dict'('option_spec')中,在那裏它只被用作常規函數。像'i.option_spec ['align'](foo)''。 – chepner

+1

在'dict'中保存引用後添加'del align'可能是一個好主意,這樣名稱就會從'class'語句的主體中移除,從而防止它被存儲爲屬性類。那麼就不會有一個名爲'align'的僞方法。 – chepner

相關問題