Как я могу сделать этот код Python более удобным и читаемым? - PullRequest
1 голос
/ 15 ноября 2009

Новичок в python, но программирую уже около 5 лет. Я подозреваю, что мне нужно многому научиться делать вещи объектно-ориентированным способом, но я знаю основы. Я планировал программировать калькулятор, который показывает, как он справляется с задачей, и знания, которые я от него получу Я только начал, и это то, что у меня есть, и это выглядит очень уродливо для меня. Как бы вы сделали это по-другому?

P.S. Это простой скрипт, который позволяет взять проблему из круглых скобок, сложить ее, показать работу, а затем оценить всю проблему.

import re

def EvalParenths(problem):
    contents = ""
    if re.match( "\(", problem):
        contents = re.match("(\(.*\))", problem)
        parenthsAnswer = contents.group(0)
        problem = problem.replace(parenthsAnswer, '')
        print "   \ \n   "  + str(eval(parenthsAnswer)) + problem
        problem = problem.replace(parenthsAnswer, '')
        answer = eval(parenthsAnswer+problem)
        print "    \ \n    " + str(answer)
    else:
        print "Didn't Find Parenthesis"

def ProblemHasParenths(problem):
    return re.match( "\(", problem)

"""""
Example Problem: (12/4)*2

"""""

problem = raw_input()

if ProblemHasParenths:
    EvalParenths(problem)

Ответы [ 4 ]

5 голосов
/ 15 ноября 2009

Некоторые проблемы:

contents = re.match("(\(.*\))", problem)

Когда ему дадут ввод (1+2)/(3+4), он попытается оценить 1+2)/(3+4.

Это также не входит во вложенные скобки, для этого вам нужно будет использовать рекурсию.

Я думаю, вам следует предпринять еще одну попытку, прежде чем вы "посмотрите на ответы".

2 голосов
/ 15 ноября 2009

Я бы, вероятно, заменил вхождения

re.match( "\(", problem)

с

problem.startswith("(")

В

contents = re.match("(\(.*\))", problem)
parenthsAnswer = contents.group(0)

вы не проверяете, соответствует ли содержимое содержимому или нет, если вы передадите ему ввод "(1", вы получите исключение при попытке оценить contents.group (0)

Не каждый использует eval в реальной программе!

Вы можете использовать pyparsing , чтобы создать полный синтаксический анализатор, но я думаю, что это то, что каждый должен попробовать самостоятельно, как упражнение хотя бы один раз!

2 голосов
/ 15 ноября 2009

Если вы хотите создать простой калькулятор, вы можете попробовать реализовать алгоритм Shunting-yard .

Но если вы хотите использовать подход регулярных выражений, я все равно сделаю это немного по-другому:

import re

#In python functions/methods usually are lowercase
#and words are seperated by _ while classes use CamelCasing
def eval_step_by_step(expression):
    """Evaluates math expression. Doesn't do any error checking.
        expression (string) - math expression"""

    print expression
    #For pretty formating.
    expr_len = len(expression)
    #While there's parentheses in the expression.
    while True:
        #re.match checks for a match only at the beginning of the string,
        #while re.search checks for a match anywhere in the string.

        #Matches all numbers, +, -, *, / and whitespace within parentheses
        #lazily (innermost first).
        contents = re.search("\(([0-9|\*|/|\+|\-|\s]*?)\)", expression) 
        #If we didn't find anything, print result and break out of loop.
        if not contents:
            #string.format() is the Python 3 way of formating strings
            #(Also works in Python 2.6).

            #Print eval(expression) aligned right in a "field" with width
            #of expr_len characters.
            print "{0:{1}}".format(eval(expression), expr_len)
            break

        #group(0) [match] is everything matching our search,
        #group(1) [parentheses_text] is just epression withing parentheses.
        match, parentheses_text = contents.group(0), contents.group(1)
        expression = expression.replace(match, str(eval(parentheses_text)))
        #Aligns text to the right. Have to use ">" here
        #because expression is not a number.
        print "{0:>{1}}".format(expression, expr_len)

#For example try: (4+3+(32-1)*3)*3
problem = raw_input("Input math problem: ")

eval_step_by_step(problem)

Он не совсем работает так же, как ваша функция, но вы можете легко внести изменения в вашу функцию, чтобы они соответствовали моей. Как видите, я также добавил много комментариев, чтобы объяснить некоторые вещи.

0 голосов
/ 15 ноября 2009

Почему вы не подходите только для двойных и совпадающих скобок? Первое совпадение для единственного ( на самом деле не является необходимым, поскольку если совпадение для двойников не удается, это означает, что для вас нет выражения для оценки.

import re

def eval_parentheses(problem):
    contents = re.match("(\(.*\))", problem)
    if contents:
    ...
    else:
        print "Couldn't find parentheses!"

Кроме того, алгоритм выбора скобок может быть немного улучшен для вложенных паренов и т. Д.

...