2009-09-02 5 views
1

私はアルゴリズムを実装するためのクラスを作成しています。このアルゴリズムは、3つのレベルの複雑さを有する。私はcalc_algorithmは、各クラスでオーバーライドされることを期待しPythonでのクラスのエイリアス

class level0: 
    def calc_algorithm(self): 
     # level 0 algorithm 
     pass 

    # more level0 stuff 

class level1(level0): 
    def calc_algorithm(self): 
     # level 1 algorithm 
     pass 

    # more level1 stuff 

class level2(level1): 
    def calc_algorithm(self): 
     # level 2 algorithm 
     pass 

    # more level2 stuff 

:それはこのようなクラスを実装するために私には意味があります。特定のコマンドラインオプションに応じて、データに対してレベル0、レベル1またはレベル2のいずれかを実行したいとします。これは私が、アルゴリズムを呼び出す方法です:

for offset in itertools.product(*map(xrange, (dim[0] - 1, dim[1] - 1, dim[2] - 1))): 
    algorithm(offset).calc_algorithm  

algorithmlevel0level1またはlevel2のいずれかです。

私は他の言語でそれを行うだろう方法は、次のとおりです。

for offset in itertools.product(*map(xrange, (dim[0] - 1, dim[1] - 1, dim[2] - 1))): 
    if (level == 0):   
     level0(offset).calc_algorithm  
    else: 
     if (level == 1):   
      level1(offset).calc_algorithm  
     else: 
      level2(offset).calc_algorithm  

は、私は何ができるように、別のクラスを参照するクラスをエイリアスにPython的な方法はあります:

algorithm = (level == 0) and level0 or (level == 1) and level1 or level2 

を呼び出して、上記のようにalgorithmを呼び出しますか?

私はこのようなクラスを書くことができアスペクト指向言語であるSpecman、中だけで比較のため

、:

struct algorithm { 
    level: uint; 
    // common stuff for all levels 

    calc_algorithm() is empty; 

    when (level == 0) { 
     calc_algorithm() is only { 
      // level 0 algorithm 
     }; 
    }; 
    when (level == 1) { 
     calc_algorithm() is only { 
      // level 1 algorithm 
     }; 
    }; 
    when (level == 1) { 
     calc_algorithm() is only { 
      // level 1 algorithm 
     }; 
    }; 

}; 

そして、私はlevel構造体のメンバを設定したら、その後、私は残りの部分を使用することができますクラスの

+0

をレベルを渡すことができます - それは「より多くのです「コマンドライン引数に基づいてクラスを選択する」、または「ユーザー入力に基づいてクラスを選択する」などの方法があります。 –

+0

そうだが、これはコマンドラインやユーザー入力から来る必要はありません。クラス間の区別は、以前の計算の結果である可能性があります。 –

答えて

11

これらの行に沿って何かをお探しですか?

dispatch = {0: level0, 1: level1, 2:level2} 
dispatch[offset].calc_algorithm 

明らかに、キー(およびoffset)はコマンドラインから来る可能性があります。

+0

あなたのコードでは、 'level0'、' level1'、 'level2'はクラスの* instances *であると仮定しています。実際にインスタンス化したいクラスです。 –

+2

これは問題ではありません。 'dispatch [offset](..)。calc_algorithm'(2つのピリオドがどこにあるか、あなたの"コンストラクタ "引数を入れてください。) – u0b34a0f6ae

4
dispatch = {0:level0, 1:level1, 2:level2} 
algo = dispatch[offset]() # "calling" a class constructs an instance. 
algo.calc_algorithm() 

あなたより内省のような場合は、次のキーがあることである

class_name = "level%d" % offset 
klass = globals()[class_name] 
algo = klass() 
algo.calc_algorithm() 
3

- クラスが「特別」であり、あなたは「エイリアス」のいくつかの異常な手段を持っている必要があるだろういくつかの他の言語とは異なりPythonでは、クラス自体は、完全に正常な変数によって参照されるファーストクラスのオブジェクトです。

「a」は、「b = a」というだけで、「b」として別名を付けることができます。

は、私は何ができるように、別のクラスを参照するクラスをエイリアスにPython的な方法はあります:

アルゴリズム=(レベル== 0)と、レベル0または(レベル== 1)とレベル1またはレベル2

まあまあ、それはまさに正しいので、すでにあなたがそれを書いたとおりに動作します!

...現代のPythonがあれば/ else式を有するがだから、今日あなたは、一般的に言うだろう:

algorithm= level0 if level==0 else level1 if level==1 else level2 

が、その後、配列アクセスは、おそらく2つの条件文よりも簡単で、次のようになります。個人的に

algorithm= (level0, level1, level2)[level] 
2

、私はいないだろう3つのクラスを作成し、3つの異なる計算方法を持つ1つのクラスを作成し、必要に応じて公式の計算方法(計算インターフェース)を変更します。たとえば :あなたは、実行時にdinamically calcFunctionを変更する必要がない場合

class algorithm: 
    def __init__(self, level = 0): 

     self.level = level 
     self.calcFunctions = {0: self.calcLevel0, 1: self.calcLevel1, 2:self.calcLevel2} 
     #initial value for calc function 
     self.setLevel(level) 

    def setLevel(self, newlevel): 
     self.level = newlevel 
     self.calc = self.calcFunctions[level]  

    def calcLevel0(self): 
     """Level 0 calc algorithm""" 
     #... 
     pass 

    def calcLevel1(self): 
     """Level 1 calc algorithm""" 
     #... 
     pass 

    def calcLevel2(self): 
     """Level 2 calc algorithm""" 
     #... 
     pass 


#class in use: 

#level (taken from command line in your case) 
level = 1 

alg = algorithm() 
alg.setLevel(level) 
alg.calc() 

、あなたはまた、これは本当にクラスエイリアシングされていないクラスのコンストラクタに

+0

これは洗練された解決策です。レベル間を区別するために 'if'ステートメントを持つ' calc'関数を1つ持っていたことを除けば、最初は考慮されました。私が別のクラスを持つのが好きな理由は、各レベルには、他のレベルでは必要ないさまざまなテーブルが必要だからです。これをすべて同じファイルにまとめると、非常に乱雑になりました。彼らは別のクラスにいる場合は、別のファイルにすることもできますので、コードを管理しやすくなります。 –

+0

私はあなたのことを理解しています。とにかく、必要なレベルに基づいて、異なるテーブルローダーを設定することもできます。 –

+0

どうすればいいですか? –

関連する問題