程序不接受参数 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] '-'
我将把它的实现留作练习。
如您所见,即使在这个简单的示例中,错误处理代码也比评估代码多,这在编写简单的编译器时并不奇怪。
我正在创建一个接受算术表达式并首先将运算符推送到 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] '-'
我将把它的实现留作练习。
如您所见,即使在这个简单的示例中,错误处理代码也比评估代码多,这在编写简单的编译器时并不奇怪。