2016-06-20 7 views
0

次のように私は、Python 3.3.3に基本的なIntepreter /仮想マシンのクラスを作成しようとしていますのメソッドの辞書を作成してください:は、どのように私はPythonの

class VirtualMachine: 

    TERM_DICT = { 
     0x01 : self.writeline, 
     0x02 : self.expression 
    } 

    def test(self): 
     opcode = 0x01 #hardcoded for testing purposes 
     if opcode in self.TERM_DICT: 
      term = self.TERM_DICT[opcode] 
      term() 
     else: 
      print("opcode not recognised") 

    def writeline(self): 
     print("Writeline") 

    def expression(self): 
     return "Hello World" 

myVM = VirtualMachine() 
myVM.test() 

私は私が手にこのスクリプトを実行してみてくださいエラーメッセージ:

Traceback (most recent call last): 
    File "testVM.py", line 1, in <module> 
    class VirtualMachine: 
    File "testVM.py", line 4, in VirtualMachine 
    0x01 : self.writeline, 
NameError: name 'self' is not defined 

どのように私はこのエラーを取り除くことができ、正しいクラスメソッドへの参照として適切に辞書を使用するを教えてください。

+2

クラスの終わりに移動してください(*実際にそれらのメソッドを定義した後*)、 'self.'(インスタンスメソッド外のスコープにはありません)を削除してください。 – jonrsharpe

+0

あなたのインデントはすべて乱れています。私はそれを修正することに行きましたが、混乱しました。コードを正しく理解できるように正しくインデントしてください。 –

+0

@LegoStormtrooprインデントを修正しました。ありがとうございます。実際のコードではうまくいきました。それはちょうどSOに貼り付けることによってちょうどうんざりされました。 – Caltor

答えて

2

ないあなたがやろうとしているが、私はこれがあなたのスタートを与えるだろうと思うかわから:

class VirtualMachine: 

    def __init__(self): 
     self.TERM_DICT = {0x01 : self.writeline, 0x02 : self.expression} 

    def test(self, opcode = 0x01): 
     if opcode in self.TERM_DICT: 
      term = self.TERM_DICT[opcode] 
      term() 
     else: 
      print("opcode not recognised") 

    def writeline(self): 
     print("Writeline") 

    def expression(self): 
     return "Hello World" 

myVM = VirtualMachine() 
myVM.test() 

テスト目的のために、あなたはおそらくreturn "Hello World"

print("Hello World")にを変更したいあなたは書き換えることができこのような test()機能:あなたはオペコード、SOMETのチェックを保つことができるコメントに基づいて

def test(self, opcode = 0x01): 
    try: 
     self.TERM_DICT[opcode]() 
    except KeyError: 
     print("opcode not recognised") 

このよう興:

def test(self, opcode = 0x01): 
    if opcode in self.TERM_DICT: 
     self.TERM_DICT[opcode]() 
    else: 
     raise KeyError(opcode) 
1

メソッドの辞書を保存すると、問題は、彼らがバウンド方法する必要があることです。

>>> myVM.writeline 
<bound method VirtualMachine.writeline of <__main__.VirtualMachine object at 0x104e78c18>> 

は、あなたがそれをバインドするインスタンスなしにバインドされたメソッドを取得することはできません(@Edwin van Mierloが行ったように)各インスタンスに対してTERM_DICTを格納するか、またはgetattrで動的にメソッド名を検索する必要があります。

は、これは単なる文字列としてメソッド名を格納し、あなたの試験方法でgetattrに一度のコールを追加し、あなたのコードに非常に低いの変更を必要とします。これは、あなたがそれぞれに1つのバインドされたメソッドのオブジェクトを作成しているだった

class VirtualMachine: 

    TERM_DICT = { 
     0x01 : "writeline", #use strings instead of bound methods! 
     0x02 : "expression" 
    } 

    def test(self): 
     opcode = 0x01 #hardcoded for testing purposes 
     if opcode in self.TERM_DICT: 
      method_name = self.TERM_DICT[opcode] 
      term = getattr(self, method_name) #use get_attr here! 
      term() 
     else: 
      print("opcode not recognised") 

    def writeline(self): 
     print("Writeline") 

    def expression(self): 
     return "Hello World" 

myVM = VirtualMachine() 
myVM.test() 

.test()を実行するときには、これはまさにバインドされたメソッドオブジェクトのためのものです。

+0

興味深い!私は、パラメータのような他のものを追加し始めたら、それがどう機能するかを見なければならないでしょう。 – Caltor

+0

あなたが受け入れた答えとほぼ同じです。唯一の顕著な違いは、このようにVirtualMachine.TEST_DICTに動的に追加して、受け入れられた答えがインスタンスごとに行う必要があるすべてのインスタンスに追加できることです。それ以外の場合は、2つの手法が同じように機能するはずです。 –

+0

Cool!私の場合、 'TEST_DICT'は不変なので、2つのオプションがあります。 – Caltor