2016-07-27 113 views
1

我有一個列表,我將使用文件作爲示例。每種類型的文件需要以不同的方式處理。我創建了一個類「MyFile」,而不是維護一個巨人,如果:elif:else:structure我創建了一個文件類型爲字典的字典。這存儲爲一個類變量。調用從方法返回的對象方法作爲方法變量

class MyFile(object): 

    def process_xlsx(self): 
     #process file stuff for Excel 
     pass 

    def process_docx(self): 
     #process file stuff for Word 
     pass 

    def get_filetype(self): 
     try: 
      return self.FileTypes[file_extension] 
     except KeyError: 
      return None #filetype not handled... yet 

    FileTypes = { 
     "XLSX": ("Excel File", process_xlsx), 
     "DOCX": ("Word Document", process_docx) 
     } 

在不同的類/對象/模塊中,我實例化MyFile類並開始逐步瀏覽這些文件。 MyFile對象已正確創建。

f = MyFile("full_file_path_and_name") 
file_type = f.get_filetype() 

file_type有一個帶有鍵和函數對象的元組。這裏有一個例子: xls_0386.xlsx - (「Excel文件」) doc_0386.docx - (「字文件」)

問:我如何調用從f.get_filetype返回的功能( )?

file_type[1]() 

返回:process_xlsx()失蹤1個人需要的位置參數: '自我'

file_type[1] 

創建沒有錯誤,但實際上從未進行呼叫(斷點從來沒有在過程中達到_ ????方法)

那麼,以這種方式調用對象方法的語法是什麼?

我知道這是有點複雜解釋我的具體情況,併爲此表示歉意。

在此先感謝。

回答

0

你用第一個參數來調用它,就是你想讓自己成爲的東西。例如:

f = MyFile("full_file_path_and_name") 
file_type = f.get_filetype() 
file_type[1](f) 

這樣,您還可以使用任何其他文件的功能。如果您只想調用file_type[1]的特定文件,請具有部分填充的功能,因此self已經是一個參數。因爲這些功能在類中聲明你可以用functools.partial

import functools 

class MyFile(object): 

    # ... 

    def get_filetype(self): 
     def partial(func): 
      return functools.partial(func, self) 
     return {"XLSX": ("Excel File", partial(process_xlsx)), 
       "DOCX": ("Word Document", partial(process_docx)) 
       }.get(self.file_extension) 

# Then you just do 

f = MyFile("full_file_path_and_name") 
file_type = f.get_filetype() 
file_type[1]() 
+0

正如你所知,這個工作完美!謝謝。我是Python的新手,我仍然試圖讓我的頭腦中的一些細節。這爲我填補了另一個。 此外,感謝您有關「部分」的更多信息。我會深入研究這一點,但這絕對是我認爲我領導的地方。 很多榮譽。 – billbris

0

做到這一點,他們必須代表從類調用了函數的對象參數self。當您嘗試在MyFile對象的上下文之外單獨調用該函數時,不再有與​​該函數調用相關聯的變量self。這就是爲什麼你的錯誤:

missing 1 required positional argument: 'self'

只要給它的MyFile實例,你已經創建爲self變量來使用:

file_type[1](f) 
+0

謝謝。這是現貨。我知道「自我」缺失,但沒有經驗知道從哪裏得到它。現在我明白了。 – billbris

1

當你創建一個class,你定義的方法它是只是功能。只有當您從類的實例中檢索到它們的名稱時,它們是否會被綁定到該實例,從而生成綁定方法。這是通過descriptor protocol完成的。

所以,當您創建FileTypes詞典:

FileTypes = { 
    "XLSX": ("Excel File", process_xlsx), 
    "DOCX": ("Word Document", process_docx) 
    } 

這些都是普通的功能。

你有三個選擇,基本上是:

  1. 不要創建的類定義時字典。創建它,當你創建一個實例,所以你可以存儲綁定方法在它:

    class MyFile(object): 
        def __init__(self):  
         self.FileTypes = { 
          "XLSX": ("Excel File", self.process_xlsx), 
          "DOCX": ("Word Document", self.process_docx) 
         } 
    

    因爲這個查找上self方法,就必然。

  2. 綁定的方法 '手動' 當你看看他們在get_filetype()

    def get_filetype(self): 
        try: 
         return self.FileTypes[file_extension].__get__(self) # binding! 
        except KeyError: 
         return None #filetype not handled... yet 
    
  3. 返回functools.partial() objectself作爲一個位置參數,而不是僅僅的功能:

    from functools import partial 
    
    def get_filetype(self): 
        try: 
         return partial(self.FileTypes[file_extension], self) # also a kind of binding 
        except KeyError: 
         return None #filetype not handled... yet 
    

所有這三種方法都會導致一個對象返回給調用者,調用者在被調用時會通過t實例MyFile()到選定的功能。

+0

這也是非常正確的。我喜歡你已經佈置的一些選項,並會考慮它們以及它們如何適合我的開發風格。非常感謝你的見解。他們相當有幫助。 – billbris