質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1403閲覧

Python: クラスのgetメソッドの戻り値の型について

退会済みユーザー

退会済みユーザー

総合スコア0

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/04/13 11:50

編集2020/04/13 12:18

前提・実現したいこと

コンピュータシステムの理論と実装を学習中です。現在8章でVM変換器をPythonで実装しようとしています。以下コードの一部です。

python

1## f_parser.py 2import re 3 4class Parser(): 5 def __init__(self, i_stream): 6 self.stream = i_stream 7 self.line_now = '\n' 8 self.commands = None 9 self.match_obj = None 10 self.command_type = None 11 self.comment = None 12 self.command_reg = re.compile('([a-zA-Z]+)?\s?([a-zA-Z0-9]+)?\s?([a-zA-Z0-9]+)?\s?(^(//){1}.*)?\s?') 13 14 self.command_dict = {'add': 'C_ARITHMETRIC', 15 'sub': 'C_ARITHMETRIC', 16 'neg': 'C_ARITHMETRIC', 17 'eq': 'C_ARITHMETRIC', 18 'gt': 'C_ARITHMETRIC', 19 'lt': 'C_ARITHMETRIC', 20 'and': 'C_ARITHMETRIC', 21 'or': 'C_ARITHMETRIC', 22 'not': 'C_ARITHMETRIC', 23 'push': 'C_PUSH', 24 'pop': 'C_POP', 25 'label': 'C_LABEL', 26 'goto': 'C_GOTO', 27 'if-goto' : 'C_IF', 28 'function' : 'C_FUNCTION', 29 'return': 'C_RETURN', 30 'call': 'C_CALL'} 31 32 33 def __del__(self): 34 self.stream.close() 35 36 37 def hasMoreCommands(self): 38 return self.line_now != '' 39 40 def advance(self): 41 self.line_now = self.stream.readline() 42 43 def commandType(self): 44 self.match_obj = self.command_reg.match(self.line_now) 45 self.commands = [self.match_obj.group(1), 46 self.match_obj.group(2), 47 self.match_obj.group(3), 48 self.match_obj.group(4)] 49 50 self.command_type = self.command_dict.get(self.commands[0]) 51 return self.command_type 52 53 54 def get_arg1(self): 55 if self.command_type == 'C_ARITHMETRIC': 56 return self.commands[0] 57 else: 58 return self.commands[1] 59 60 61 def get_arg2(self): 62 if self.command_type in ['C_PUSH', 'C_POP', 'C_FUNCTION', 'C_CALL']: 63 return self.commands[2] 64 else: 65 return None 66 67

実現したいことは、push constant 2 のようなVMコードをパースして以下のような関数に投げて処理がしたいです。

python

1 2## code_writer.py 3 4def writePush(self, arg1, arg2): 5 if arg1 == 'static': 6 address = ['@' + self.filename + '.' + arg2] 7 process = ['D=M'] 8 9 elif arg1 == 'constant': 10 address = ['@' + str(self.mapping.get(arg1) + int(arg2))] 11 process = ['D=A'] 12 13 elif arg1 in ['pointer', 'temp']: 14 address = ['@' + str(self.mapping.get(arg1))] 15 process = ['A=M' ,'A=A+{0}'.format(arg2), 'D=M'] 16 17 elif arg1 in ['local', 'argument', 'this', 'that']: 18 address = ['@' + self.mapping.get(arg1)] 19 process = ['A=M', 'A=A+{0}'.format(arg2), 'D=M'] 20 21 22 command = '\n'.join(address + process) 23 self.o_stream.write(command)

get_arg1,get_arg2はf_parser.pyに記述されています。やりたい処理は同じディレクトリ内のcode_writer.pyに書いてあります。実際にはWritePush()は、vm_translator.pyというファイル(これも同じディレクトリ内)でVM_Translatorクラスのメソッド内の処理として呼び出されています。

python

1# vm_translator.py 2 3import f_parser 4import code_writer 5 6 7class VM_Translator(): 8 def __init__(self, dir, filename): 9 self.dir = dir 10 self.filename = filename 11 self.i_stream = open(dir+'/'+filename + '.vm', 'r') 12 self.parser = f_parser.Parser(self.i_stream) 13 self.codeWriter = code_writer.codeWriter(self.dir, self.filename, self.parser) 14 15 def Translate(self): 16 while self.parser.hasMoreCommands(): 17 self.parser.advance() 18 19 line_now = self.parser.line_now 20 command_type = self.parser.commandType() 21 22 if command_type == None: 23 continue 24 25 if command_type == 'C_PUSH': 26 arg1 = self.parser.get_arg1 27 arg2 = self.parser.get_arg2 28 self.codeWriter.writePush(arg1, arg2) 29 30 if command_type == 'C_POP': 31 arg1 = self.parser.get_arg1 32 arg2 = self.parser.get_arg2 33 self.codeWriter.writePop(arg1, arg2) 34 35 if command_type == 'C_ARITHMETRIC': 36 command = self.parser.get_arg1() 37 self.codeWriter.writeArithmetric(command) 38 39 else: 40 print('Finish VM translation.') 41 42

起きていること

始めに示したクラスのget_arg1,get_arg2メソッドでarg1とarg2を取得して処理しようとしましたが、以下のエラーが返ってきました。

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "~~~~\vm_translator.py", line 26, in Translate self.codeWriter.writePush(arg1, arg2) File "~~~~\code_writer.py", line 53, in writePush command = '\n'.join(address + process) UnboundLocalError: local variable 'address' referenced before assignment

さらに、arg1とarg2の中身を確認すると

<bound method Parser.get_arg1 of <f_parser.Parser object at 0x0000023461595CD0>>

となっており、型としてstringを期待しているのにParserクラスのオブジェクトとして表示されています。エラー自体はget_argの戻り値がどのif文にも引っかからなかったことが原因です(さらにそのような場合のケアもしていない)。get_argメソッドの戻り値をarg1 == 'static'のような条件分岐に引っ掛けるにはどうすればよいでしょうか?クラス定義と継承あたりの基本事項と思われますが、どうぞ宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2020/04/13 11:59

writePush はどのように呼び出したのでしょうか?
quickquip

2020/04/13 12:00

> def writePush(self, arg1, arg2): がどこに書いてあるのか、 > 始めに示したクラスのget_arg1,get_arg2メソッドでarg1とarg2を取得して処理しようとしましたが 具体的になにをどう呼び出したのか、 とエラーの全文が載っていません。質問に追記しましょう。
guest

回答1

0

ベストアンサー

Python

arg1 = self.parser.get_arg1()
arg2 = self.parser.get_arg2()
self.codeWriter.writePush(arg1, arg2)

呼び出さないと返り値は返ってきません。

Python

1arg1 = self.parser.get_arg1 2arg2 = self.parser.get_arg2 3self.codeWriter.writePush(arg1, arg2)

投稿2020/04/13 12:35

LouiS0616

総合スコア35668

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/04/13 13:03

単純な見落としでした、、、。ご指摘ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問