Đây là một trình thông dịch ký hiệu Python postfix sử dụng một ngăn xếp để đánh giá các biểu thức. Có thể làm cho chức năng này hiệu quả hơn và chính xác hơn không?Thông tin này có thể được thực hiện hiệu quả hơn và chính xác hơn không?
#!/usr/bin/env python
import operator
import doctest
class Stack:
"""A stack is a collection, meaning that it is a data structure that
contains multiple elements.
"""
def __init__(self):
"""Initialize a new empty stack."""
self.items = []
def push(self, item):
"""Add a new item to the stack."""
self.items.append(item)
def pop(self):
"""Remove and return an item from the stack. The item
that is returned is always the last one that was added.
"""
return self.items.pop()
def is_empty(self):
"""Check whether the stack is empty."""
return (self.items == [])
# Map supported arithmetic operators to their functions
ARITHMETIC_OPERATORS = {"+":"add", "-":"sub", "*":"mul", "/":"div",
"%":"mod", "**":"pow", "//":"floordiv"}
def postfix(expression, stack=Stack(), operators=ARITHMETIC_OPERATORS):
"""Postfix is a mathematical notation wherein every operator follows all
of its operands. This function accepts a string as a postfix mathematical
notation and evaluates the expressions.
1. Starting at the beginning of the expression, get one term
(operator or operand) at a time.
* If the term is an operand, push it on the stack.
* If the term is an operator, pop two operands off the stack,
perform the operation on them, and push the result back on
the stack.
2. When you get to the end of the expression, there should be exactly
one operand left on the stack. That operand is the result.
See http://en.wikipedia.org/wiki/Reverse_Polish_notation
>>> expression = "1 2 +"
>>> postfix(expression)
3
>>> expression = "5 4 3 + *"
>>> postfix(expression)
35
>>> expression = "3 4 5 * -"
>>> postfix(expression)
-17
>>> expression = "5 1 2 + 4 * + 3 -"
>>> postfix(expression, Stack(), ARITHMETIC_OPERATORS)
14
"""
if not isinstance(expression, str):
return
for val in expression.split(" "):
if operators.has_key(val):
method = getattr(operator, operators.get(val))
# The user has not input sufficient values in the expression
if len(stack.items) < 2:
return
first_out_one = stack.pop()
first_out_two = stack.pop()
operand = method(first_out_two, first_out_one)
stack.push(operand)
else:
# Type check and force int
try:
operand = int(val)
stack.push(operand)
except ValueError:
continue
return stack.pop()
if __name__ == '__main__':
doctest.testmod()
Piet, đây là một câu trả lời tuyệt vời. Thời gian thực hiện chương trình đã giảm. Tuy nhiên, tôi có một câu hỏi. Trong 'postfix', bạn có thể nắm bắt tất cả các ngoại lệ có thể và bong bóng chúng lên đến người gọi như là một' ngoại lệ 'tùy chỉnh, hay bạn sẽ kết thúc cuộc gọi đến 'postfix' trong một khối thử/trừ toàn diện? – simeonwillbanks
simeonwillbanks: Khi nghi ngờ về ngoại lệ, không làm gì cả. :-) Chúng đặc biệt vì một lý do! Thật hiếm khi xác định ngoại lệ của riêng bạn: không làm điều đó khi [ngoại lệ tích hợp] (http://docs.python.org/library/exceptions.html) đủ. Ngoài ra, không cảm thấy bắt buộc phải viết "toàn diện" thử/trừ các khối: hầu như tất cả các mã đều cho phép hầu như tất cả các ngoại lệ vượt qua và chỉ xử lý các ngoại lệ mà chúng * biết * chúng sẽ xử lý. (Một trong những nơi duy nhất bạn muốn có một trình xử lý ngoại lệ bắt được ở cấp cao nhất của một ứng dụng sản xuất, ví dụ, để báo cáo lỗi.) –
Piet, cảm ơn lời khuyên. Tôi chấp nhận giải pháp của bạn! P.S. Mùa hè vừa qua, tôi đã đến Cape Town để tham dự World Cup 2010. Đó là một thành phố đáng yêu, và tôi hy vọng sẽ trở lại một ngày. – simeonwillbanks