-3

私はPythonで単純な式評価器を実装しようとしていますが、パーサーメソッドで立ち往生しています.Belowは私のコードスニペットです.

    class Number:
    def __init__(self,value):
        self.value=value
    def execute(self):
        return self.value

class Plus:
    def __init__(self,left,right):
        self.left=left
        self.right=right
    def execute(self):
        return self.left+self.right

class Minus:
    def __init__(self,left,right):
        self.left=left
        self.right=right
    def execute(self):
        return self.left-self.right

class Multiply:
    def __init__(self,left,right):
        self.left=left
        self.right=right
    def execute(self):
        return self.left*self.right
import re
def parser(input):
    stack=[]
    token_pat = re.compile("\s*(?:(\d+)|(.))")
    for number, operator in token_pat.findall(input):


        if number:
            stack.append(Number(int(number)))

        else:
            first,second=stack.pop(),stack.pop()

            if operator=="+":
                stack.append(Plus(first,second))
            elif operator=="-":
                stack.append(Minus(first,second))
            elif operator=="*":
                stack.append(Multiply(first,second))
            else:
                raise SyntaxError("unknown operator")
    print stack[0].execute()


if __name__=="__main__":
    parser('1 2 +')

上記のコードを実行すると、次のエラーが発生します。誰でも私のコードを確認できますか?

Traceback (most recent call last):
  File "Interpreter.py", line 52, in <module>
    parser('1 2 +')
  File "Interpreter.py", line 48, in parser
    print stack[0].execute()
  File "Interpreter.py", line 12, in execute
    return self.left+self.right
TypeError: unsupported operand type(s) for +: 'instance' and 'in
4

2 に答える 2

5

クラシック クラスを使用しているため、エラー メッセージはわかりにくいものです。新しいスタイルのクラス (つまり、 から継承object) を使用すると、より合理的な結果が得られます。

TypeError: unsupported operand type(s) for +: 'Number' and 'Number'

Number オブジェクトの代わりに を使用するか、と friendsintを実装して追加ロジックを実装するか、 に評価ロジックを追加します。__add__Plus.execute

また、Python のビルトインを再実装していることにも注意してください。さらに、executeメソッドを持つことはほとんどアンチパターンです。はるかに短い実装は次のようになります

import functools,operator,re

def parser(inp):
    stack=[]
    token_pat = re.compile("\s*(?:(\d+)|(.))")
    for number, op in token_pat.findall(inp):
        if number:
            stack.append(functools.partial(lambda i:i, int(number)))
        else:
            first,second=stack.pop(),stack.pop()
            try:
                op = {
                    '+': operator.add,
                    '-': operator.sub,
                    '*': operator.mul
                }[op]
            except KeyError:
                raise SyntaxError("unknown operator")

            stack.append(functools.partial(lambda op,first,second:
                        op(first(), second()), op, first, second))
    print(stack[0]())

if __name__=="__main__":
    parser('1 2 + 3 *')
于 2012-08-26T10:37:51.510 に答える
1

自分で基本的なデバッグを行うことに興味がないので:

sucmac: $ python out.py 
> /Users/xxxx/out.py(13)execute()
-> return self.left+self.right
(Pdb) self.left
<__main__.Number instance at 0x10043f3f8>
(Pdb) self.right
<__main__.Number instance at 0x10042f248>
(Pdb) right
*** NameError: name 'right' is not defined
(Pdb) self.right.__dict__
{'value': 1}

あなたは明らかにしたい

return self.right.value + self.left.value
于 2012-08-26T10:38:27.567 に答える