程序不接受参数 Python

Program does not accept argument Python

我正在创建一个接受算术表达式并首先将运算符推送到 stacl 的后缀计算器。

./pythonfilename 3 4 1 + - 被用作我的输入。但是,由于没有显示输出,我尝试调试我的程序以了解为什么我的程序没有接受我的论点。 不会导致打印任何输出。我按 Ctrl+C 显示回溯调用,它指出 x = sys.stdin.readlines.

#!/usr/bin/python

import sys
import fileinput

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self,item):
        self.items.append(item)

    def pop(self):
        return self.items(pop)

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

    def is_number(line):
        try:
            float(line)
        except ValueError:
            return False        

def infixtoPostfix():
    initStack=Stack()
    x = sys.stdin.readlines() #read user input 
    for lines in x:#for lines in fileinput.input():
        for line in lines.strip().split(" "):
            if is_number(line):
                initStack.push(line)
                line = float(line)
            elif line =='+':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum + secNum
                initStack.push(result)
                print initStack.peek()              

            elif line == '-':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum - secNum
                initStack.push(result)
                print initStack.peek()

            elif line == '*':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum * secNum
                initStack.push(result)
                print initStack.peek()
            elif line == "/":
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum / secNum
                initStack.push(result)
                print initStack.peek()
            elif line == "%":
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum % secNum
                initStack.push(result)
                print initStack.peek()

infixtoPostfix()

./python文件名 3 4 1 + -

实际上 3 4 1 + - 作为参数而不是输入传递。

如果您想从文件中读取,请使用 open('filename')

使用 ./pythonfilename '3 4 1 + -'

x = [sys.argv[1]]

代替 x = sys.stdin.readlines()

但是您的代码仅处理单个输入作为参数

从管道 (cat ... | python myprog.py) 读取的标准方法是

import sys

for line in sys.stdin:
    print ">", line

line 将包含最后的 '\n'

如果您想在命令行 (python myprog.py 3 4 1 + -) 上获取参数,您可以使用 sys.argv[1:]sys.argv[0] 包含 myprog.py)。

要获得一致的输入词法,您需要首先检查 sys.argv,然后拆分 sys.stdin:

def lex_input():
    "Returns a list of tokens."
    tokens = []
    if len(sys.argv) > 1:
        tokens = sys.argv[1:]
    else:
        for line in sys.stdin:
            tokens += line.split()
    return tokens

那么您只需要更改 infixPostfix() 函数以使用此标记数组(而不是在同一个函数中同时进行解析和求值)。

ps:一种更简洁的写单个子句的方式是:

elif token == '+':
    push(pop() + pop())

但这取决于您要完成的目标..

更新: 完整的解决方案

Update2: 带有调试语句以可视化堆栈(为简洁起见,删除了 Stack class 以支持常规列表)

import sys

STACK = []
push = STACK.append
pop = STACK.pop

OPERATIONS = {
    '+': lambda b, a: a + b,
    '-': lambda b, a: a - b,
    '*': lambda b, a: b * a,
    '/': lambda b, a: b / a,
}

def infixtoPostfix(tokens):
    print '%-15s %5s %-15s' % ('STACK before', 'token', 'STACK after')
    print '-'*15, '-'*5, '-'*15

    for token in tokens:
        print '%15s %5r' % (STACK, token),

        if token not in OPERATIONS:
            push(int(token))
        else:
            push(OPERATIONS[token](pop(), pop()))

        print '%15s' % STACK

def lex_input():
    "Returns a list of tokens."
    tokens = []
    if len(sys.argv) > 1:
        tokens = sys.argv[1:]
    else:
        for line in sys.stdin:
            tokens += line.split()
    return tokens

if __name__ == "__main__":
    infixtoPostfix(lex_input())
    # well formed programs should leave a single value on the STACK
    print "\nResult is:", STACK[0]

测试:

(dev) go|c:\srv> python rpn.py 3 4 1 + -
STACK before    token STACK after
--------------- ----- ---------------
             []   '3'             [3]
            [3]   '4'          [3, 4]
         [3, 4]   '1'       [3, 4, 1]
      [3, 4, 1]   '+'          [3, 5]
         [3, 5]   '-'            [-2]

Result is: -2

(如果 rpn.txt 包含 3 4 1 + -cat rpn.txt | python rpn.py 将输出相同的内容)。

如果你尝试一个有语法错误的 rpn 程序,那么程序会抛出一个异常,例如:

(dev) go|c:\srv> python rpn.py 3 4 + -
STACK before    token STACK after
--------------- ----- ---------------
             []   '3'             [3]
            [3]   '4'          [3, 4]
         [3, 4]   '+'             [7]
            [7]   '-'
Traceback (most recent call last):
  File "rpn.py", line 60, in <module>
    infixtoPostfix(lex_input())
  File "rpn.py", line 45, in infixtoPostfix
    push(OPERATIONS[token](pop(), pop()))
  File "rpn.py", line 26, in pop
    return STACK.pop()
IndexError: pop from empty list

在真正的编译器中这会很糟糕,因为您不希望最终用户看到您的实现细节。相反,您想给他们一条诊断错误消息,以及您的程序找到它的确切位置。

在这种情况下,这并不难。我省略了打印堆栈的调试语句:

def infixtoPostfix(tokens):
    # make a copy of the input, for use in error handling
    input_tokens = tokens[:]  
    try:
        for i, token in enumerate(tokens):
            if token not in OPERATIONS:
                push(int(token))
            else:
                push(OPERATIONS[token](pop(), pop()))
    except IndexError:
        print 'Detected Syntax Error at token no.:', i + 1  # people count from 1..
        print ' '.join(input_tokens)
        print '%s%s' % ('-' * (1 + len(' '.join(input_tokens[:i]))), '^')
        push('SYNTAX ERROR')  # the top of the stack contains the result of the current operation..

需要对结果打印做一个小改动,打印列表中的最后一个元素 (STACK[-1]),这是堆栈的顶部,而不是依赖于 list/stack 只有一个元素最后:

if __name__ == "__main__":
    infixtoPostfix(lex_input())
    # well formed programs should leave a single value on the STACK
    print "\nResult is:", STACK[-1]

如果我们为这个版本提供语法错误的程序:

(dev) go|c:\srv> python rpn.py 34 4 + -
Detected Syntax Error at token no.: 4
34 4 + -
-------^

Result is: SYNTAX ERROR

我们收到一条正确的错误消息,其中有一点尖锐的 'graphic' 指示检测到错误的位置。

我们可以走得更远,因为我们知道我们所有的操作都需要堆栈上的两个元素,并给出更详细的错误消息,例如:

Syntax Error at token "-":  Stack underflow
   The "-" operation requires two stack arguments and the stack 
   contained only one:

        Stack      token
        ---------- -----
        [37]        '-'

我将把它的实现留作练习。

如您所见,即使在这个简单的示例中,错误处理代码也比评估代码多,这在编写简单的编译器时并不奇怪。