2016-07-27 18 views
1

私は物事のリストを持っていますが、私は例としてファイルを使用します。各タイプのファイルは、異なる方法で処理する必要があります。私はクラス「MyFile」を作成し、巨大なif: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 - ( 'Wordファイル'、)

質問:私は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は既に引数です。あなたは、これらの機能は、クラス内で宣言されているので、彼らは関数を呼び出しています、そのクラスからオブジェクトを表す引数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

でこれを行うことができます。 MyFileオブジェクトのコンテキスト外で、その関数を個別に呼び出そうとすると、もはや関数呼び出しに関連付けられたself変数がありません。あなたがエラーを取得する理由です:

missing 1 required positional argument: 'self'

ただ、それをあなたがすでにself変数として使用するために作成したMyFileのインスタンスを与える:あなたはclassを作成するとき

file_type[1](f) 
+0

ありがとうございます。これは上のスポットです。私は "自己"が行方不明であることを知っていましたが、それを得る場所に関する経験はありませんでした。今私は知っている。 – billbris

1

を、あなたが定義する方法それは機能だけですです。クラスのインスタンスから名前を取得した場合にのみ、そのインスタンスにバインドされ、バインドされたメソッドが生成されます。これはdescriptor protocolを介して行われます。

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

ものはプレーンな機能です:

はつまり、あなたのFileTypes辞書を作成するとき。

あなたは基本的に3つのオプション、持っている:

  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()でそれらを調べる:

    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 
    
:だけではなく、関数の位置引数として self

def get_filetype(self): 
    try: 
     return self.FileTypes[file_extension].__get__(self) # binding! 
    except KeyError: 
     return None #filetype not handled... yet 
  • 戻るfunctools.partial() object

    3つのアプローチはすべて、呼び出し元に返されるオブジェクトをもたらします。呼び出されると、そのオブジェクトは、選択された機能にMyFile()のtインスタンスを追加します。

  • +0

    これもすべて正しいです。私はあなたがレイアウトしたオプションのいくつかと、それらを考慮し、自分の開発スタイルにどのように適合するのが好きです。あなたの洞察力をどうもありがとうございます。彼らはかなり役に立ちます。 – billbris

    関連する問題