from collections import deque
def postfixExpression(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
print(ex, stack)
try:
stack.append(int(ex))
except ValueError:
b = stack.pop()
a = stack.pop()
switcher = {
"+" : a + b,
"-" : a - b,
"*" : a * b,
"/" : int(a / b),
"^" : a ** b,
}
if ex not in switcher.keys():
raise ValueError(f"Wrong expression-> {ex}")
else:
stack.append(switcher.get(ex))
return stack.pop()
expression = "2 3 7 - 7 + 9 7 2 + - * *"
print(f"\nResult {postfixExpression(expression)}")
上面是一个Python的Postfix评估程序。它适用于大多数情况。
但是当我使用输入
"2 3 7 - 7 + 9 7 2 + - * *"
时,它给出了ZeroDivisionError
,即使我没有在输入中使用除法(/
)。
错误信息:
$ python temp/temp.py
4 deque([])
6 deque([4])
* deque([4, 6])
2 deque([24])
1 deque([24, 2])
- deque([24, 2, 1])
+ deque([24, 1])
7 deque([25])
7 deque([25, 7])
+ deque([25, 7, 7])
7 deque([25, 14])
6 deque([25, 14, 7])
+ deque([25, 14, 7, 6])
* deque([25, 14, 13])
* deque([25, 182])
3 deque([4550])
7 deque([4550, 3])
- deque([4550, 3, 7])
7 deque([4550, -4])
+ deque([4550, -4, 7])
9 deque([4550, 3])
7 deque([4550, 3, 9])
2 deque([4550, 3, 9, 7])
+ deque([4550, 3, 9, 7, 2])
- deque([4550, 3, 9, 9])
* deque([4550, 3, 0])
Traceback (most recent call last):
File "C:\Users\...\temp.py", line 11, in postfixExpression
stack.append(int(ex))
ValueError: invalid literal for int() with base 10: '*'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\...\temp.py", line 52, in main
print(f"\nresult {postfixExpression(expression)}")
File "C:\Users\...\temp.py", line 19, in postfixExpression
"/" : int(a / b),
ZeroDivisionError: division by zero
当我评论切换器字典中的
"/" : int(a / b),
行时,它给出了预期的答案,即0。
任何人都可以解释为什么我会收到此错误(主要)以及如何解决它?
问题是您在设置 switcher
字典时正在评估
所有操作。因此,无论您的代码遇到哪个运算符,它都会计算堆栈顶部两个值的和、差、乘积和商。然后它会查看操作符来决定实际使用哪一个。在这种情况下,您的
b
值为零,因此它确实试图除以零。
有多种方法可以解决此问题,包括(但不限于):
lambda
字典中的switcher
函数,并且只调用需要的函数 switcher = {
"+" : lambda: a + b,
"-" : lambda: a - b,
"*" : lambda: a * b,
"/" : lambda: int(a / b),
"^" : lambda: a ** b,
}
if ex not in switcher:
raise ValueError(f"Wrong expression-> {ex}")
else:
stack.append(switcher[ex]()) # <- note the added () here
match
语句直接在代码中计算适当的值,而不是使用字典(这需要 Python 3.10+) match ex:
case "+":
val = a + b
case "-":
val = a - b
case "*":
val = a * b
case "/":
val = int(a / b)
case "^":
val = a ** b
case _:
raise ValueError(f"Wrong expression-> {ex}")
stack.append(val)
if
-elif
链直接在代码中计算适当的值,而不是使用字典 if ex == "+":
val = a + b
elif ex == "-":
val = a - b
elif ex == "*":
val = a * b
elif ex == "/":
val = int(a / b)
elif ex == "^":
val = a ** b
else:
raise ValueError(f"Wrong expression-> {ex}")
stack.append(val)
无论如何,我建议您将计算操作放入其自己的函数中,而不是将其嵌入循环中间。类似的东西
def calculate_value(op, a, b):
... # Something based on what I've shown above
def postfixExpression(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
print(ex, stack)
try:
stack.append(int(ex))
except ValueError:
b = stack.pop()
a = stack.pop()
stack.append(calculate_value(ex, a, b))
return stack.pop()
根据要求:使用
lambda
函数的测试代码:
from collections import deque
def postfixExpression(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
print(ex, stack)
try:
stack.append(int(ex))
except ValueError:
b = stack.pop()
a = stack.pop()
switcher = {
"+" : lambda: a + b,
"-" : lambda: a - b,
"*" : lambda: a * b,
"/" : lambda: int(a / b),
"^" : lambda: a ** b,
}
if ex not in switcher.keys():
raise ValueError(f"Wrong expression-> {ex}")
else:
stack.append(switcher.get(ex)())
return stack.pop()
expression = "2 3 7 - 7 + 9 7 2 + - * *"
print(f"\nResult {postfixExpression(expression)}")
有输出
2 deque([])
3 deque([2])
7 deque([2, 3])
- deque([2, 3, 7])
7 deque([2, -4])
+ deque([2, -4, 7])
9 deque([2, 3])
7 deque([2, 3, 9])
2 deque([2, 3, 9, 7])
+ deque([2, 3, 9, 7, 2])
- deque([2, 3, 9, 9])
* deque([2, 3, 0])
* deque([2, 0])
Result 0
我相信这就是您实际上想要实现的目标,但很难说,因为您没有提供手动解决的示例或预期输出:
from collections import deque
switcher = {
"+" : lambda a,b:a + b,
"-" : lambda a,b:a - b,
"*" : lambda a,b:a * b,
"/" : lambda a,b:a // b,
"^" : lambda a,b:a ** b,
}
def postfixExpression(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
print(ex, stack)
if ex.isnumeric():
stack.append(int(ex))
elif ex in switcher:
stack.append(switcher[ex](stack.pop(),stack.pop()))
else:
raise ValueError(f"Wrong expression-> {ex}")
return stack.pop()
expression = "2 3 7 - 7 + 9 7 2 + - * *"
print(f"\nResult {postfixExpression(expression)}")
编辑:只是对所提供的解决方案进行快速比较,这里是代码:
from collections import deque
def postfixExpression_OP_LAMBDA(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
try:
stack.append(int(ex))
except ValueError:
b = stack.pop()
a = stack.pop()
switcher = {
"+" : lambda a,b: a + b,
"-" : lambda a,b: a - b,
"*" : lambda a,b: a * b,
"/" : lambda a,b: int(a / b),
"^" : lambda a,b: a ** b,
}
if ex not in switcher.keys():
raise ValueError(f"Wrong expression-> {ex}")
else:
stack.append(switcher.get(ex)(a,b))
return stack.pop()
def postfixExpression_MATCH(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
try:
stack.append(int(ex))
except ValueError:
b = stack.pop()
a = stack.pop()
match ex:
case "+":
val = a + b
case "-":
val = a - b
case "*":
val = a * b
case "/":
val = int(a / b)
case "^":
val = a ** b
case _:
raise ValueError(f"Wrong expression-> {ex}")
stack.append(val)
return stack.pop()
switcher_ = {
"+" : lambda a,b:a + b,
"-" : lambda a,b:a - b,
"*" : lambda a,b:a * b,
"/" : lambda a,b:a // b,
"^" : lambda a,b:a ** b,
}
def postfixExpression_OM(expression: str) -> int:
if not expression:
return -1
expression_list = expression.split(" ")
stack = deque()
for ex in expression_list:
if ex.isnumeric():
stack.append(int(ex))
elif ex in switcher_:
stack.append(switcher_[ex](stack.pop(),stack.pop()))
else:
raise ValueError(f"Wrong expression-> {ex}")
return stack.pop()
expression = "2 3 7 - 7 + 9 7 2 + - * *"
以及一个快速比较基准: 我的解决方案速度快 3 到 4 倍,具体取决于您的操作和正确使用 lambda。如果您重命名 a 或 b,@lxop 提供的解决方案将会失败,因为他依赖于极其糟糕的变量范围(更多详细信息:https://www.youtube.com/watch?v=fZE6ZWde-Os)。