Стек - доработка по коду, питон. Нужна помощь!
Пытался исправить две ошибки, на которые указал наставник(ниже опишу их) - и после какого-то момента, перестал работать весь код, вылезает тупо 3 traceback'a. Прошу помощи, в исправлении ошибок(я думаю, что они достаточно легкие, но не понимаю, как их вылить в код).
Ошибки:
Строка 29: stack.push(int(element))
Для работы Калькулятора не важна конкретная функция, превращающая "строки в числа" (оцифровщик). Поэтому лучше сделать универсальнее. Пусть решающая функция получает "оцифровщик" необязательным параметром, у которого умолчание int. Тогда калькулятор сможет работать и с числами типа float/complex/Decimal/Rational/...
Строка 8:9 -
def pop(self):
self.items.pop()
Нужен страхующий код, так как этот вызов может сбоить
Задача: Задание связано с обратной польской нотацией. Она используется для парсинга арифметических выражений. Еще её иногда называют постфиксной нотацией. В постфиксной нотации операнды расположены перед знаками операций. Пример 1:
3 4 +
означает 3 + 4 и равно 7
Пример 2:
12 5 /
Так как деление целочисленное, то в результате получим 2.
Пример 3:
10 2 4 * -
означает 10 - 2 * 4 и равно 2
Разберём последний пример подробнее:
Знак * стоит сразу после чисел 2 и 4, значит к ним нужно применить операцию, которую этот знак обозначает, то есть перемножить эти два числа. В результате получим 8. После этого выражение приобретёт вид:
10 8 -
Операцию «минус» нужно применить к двум идущим перед ней числам, то есть 10 и 8. В итоге получаем 2.
Рассмотрим алгоритм более подробно. Для его реализации будем использовать стек. Для вычисления значения выражения, записанного в обратной польской нотации, нужно считывать выражение слева направо и придерживаться следующих шагов: Обработка входного символа:
Если на вход подан операнд, он помещается на вершину стека.
Если на вход подан знак операции, то эта операция выполняется над требуемым количеством значений, взятых из стека в порядке добавления. Результат выполненной операции помещается на вершину стека.
Если входной набор символов обработан не полностью, перейти к шагу 1. После полной обработки входного набора символов результат вычисления выражения находится в вершине стека. Если в стеке осталось несколько чисел, то надо вывести только верхний элемент.
Замечание про отрицательные числа и деление: в этой задаче под делением понимается математическое целочисленное деление. Это значит, что округление всегда происходит вниз. А именно: если a / b = c, то b ⋅ c — это наибольшее число, которое не превосходит a и одновременно делится без остатка на b. Например, -1 / 3 = -1. Будьте осторожны: в C++, Java и Go, например, деление чисел работает иначе. В текущей задаче гарантируется, что деления на отрицательное число нет.
Формат ввода
В единственной строке дано выражение, записанное в обратной польской нотации. Числа и арифметические операции записаны через пробел.
На вход могут подаваться операции: +, -, *, / и числа, по модулю не превосходящие 10000.
Гарантируется, что значение промежуточных выражений в тестовых данных по модулю не больше 50000.
Формат вывода
Выведите единственное число — значение выражения.
Пример 1:
Ввод:
2 1 + 3 *
Вывод:
9
Пример 2:
Ввод:
7 2 + 4 * 2 +
Вывод:
38
Мой код:
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self): - 8:9
self.items.pop()
def size(self):
return len(self.items)
OPERATORS = {'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
'*': lambda x, y: x * y,
'/': lambda x, y: x // y}
def calculator(line, stack=None, operators=OPERATORS):
stack = Stack() if stack is None else stack
for element in line:
if element in operators:
el1, el2 = stack.pop(), stack.pop()
stack.push(operators[element](el1, el1))
else:
try:
stack.push(int(element)) - 29 строка
except:
raise KeyError('WRONG_KEY')
return stack.pop()
if __name__ == '__main__':
line = input().split()
print(calculator(line))
Ошибки при выводе кода:
Traceback (most recent call last):
File "final_b_13.py", line 37, in <module>
print(calculator(line))
File "final_b_13.py", line 26, in calculator
stack.push(operators[element](el1, el1))
File "final_b_13.py", line 15, in <lambda>
OPERATORS = {'+': lambda x, y: x + y,
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
Ответы (1 шт):
Первая ошибка - забыли return в функции Stack.pop().
Вторая ошибка - арифметическую операцию проводите с одним и тем же элементом. Надо stack.push(operators[element](el2, el1)), а у вас el1, el1.
Остальную доработку см в коде:
import math
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self): #- 8:9
try:
return self.items.pop()
except IndexError:
raise IndexError('Недостаточно операндов для вычисления.')
def size(self):
return len(self.items)
OPERATORS = {'+': lambda x, y: x + y,
'-': lambda x, y: x - y,
'*': lambda x, y: x * y,
'/': lambda x, y: x / y,
'%': lambda x, y: x % y,
'^': lambda x, y: x ** y}
def MyInt(value):
if isinstance(value, str):
return int(value)
return math.floor(value)
def calculator(line, stack=None, converter=int, operators=OPERATORS):
stack = Stack() if stack is None else stack
for element in line:
if element in operators:
el1, el2 = stack.pop(), stack.pop()
try:
stack.push(converter(operators[element](el2, el1)))
except ZeroDivisionError:
raise ZeroDivisionError(f'Деление на 0 при вычислении "{el2} {element} {el1}".')
except TypeError:
raise TypeError(f'Неподдерживаемая операция "{element}" для типа {converter.__name__}.')
else:
try:
stack.push(converter(element)) #- 29 строка
except:
raise KeyError(f'Невозможно преобразовать "{element}" в {converter.__name__} или неподдерживаемая операция.')
if stack.size() > 1:
raise IndexError('Некорректное выражение - в стеке остались элементы.')
return stack.pop()
if __name__ == '__main__':
from decimal import Decimal
#line = input().split()
for line in ("10 2 4 * -", "12 5 /", "-1 3 /", "1.5 3.7 + 2.1 *", "2+3j -5-7j *", "2 3 ^ 3 %", "2 0 /", "1 2 3 +", "1 2 + *"):
print(f'\n Выражение : "{line}"')
line = line.split()
for t in (int, MyInt, float, complex, Decimal):
print(f"{t.__name__:>10} = ", end='')
try:
print(calculator(line, converter=t))
except (KeyError, IndexError, ZeroDivisionError, TypeError) as err:
print("Ошибка!", err)
Выражение : "10 2 4 * -"
int = 2
MyInt = 2
float = 2.0
complex = (2+0j)
Decimal = 2
Выражение : "12 5 /"
int = 2
MyInt = 2
float = 2.4
complex = (2.4+0j)
Decimal = 2.4
Выражение : "-1 3 /"
int = 0
MyInt = -1
float = -0.3333333333333333
complex = (-0.3333333333333333+0j)
Decimal = -0.3333333333333333333333333333
Выражение : "1.5 3.7 + 2.1 *"
int = Ошибка! 'Невозможно преобразовать "1.5" в int или неподдерживаемая операция.'
MyInt = Ошибка! 'Невозможно преобразовать "1.5" в MyInt или неподдерживаемая операция.'
float = 10.920000000000002
complex = (10.920000000000002+0j)
Decimal = 10.92
Выражение : "2+3j -5-7j *"
int = Ошибка! 'Невозможно преобразовать "2+3j" в int или неподдерживаемая операция.'
MyInt = Ошибка! 'Невозможно преобразовать "2+3j" в MyInt или неподдерживаемая операция.'
float = Ошибка! 'Невозможно преобразовать "2+3j" в float или неподдерживаемая операция.'
complex = (11-29j)
Decimal = Ошибка! 'Невозможно преобразовать "2+3j" в Decimal или неподдерживаемая операция.'
Выражение : "2 3 ^ 3 %"
int = 2
MyInt = 2
float = 2.0
complex = Ошибка! Неподдерживаемая операция "%" для типа complex.
Decimal = 2
Выражение : "2 0 /"
int = Ошибка! Деление на 0 при вычислении "2 / 0".
MyInt = Ошибка! Деление на 0 при вычислении "2 / 0".
float = Ошибка! Деление на 0 при вычислении "2.0 / 0.0".
complex = Ошибка! Деление на 0 при вычислении "(2+0j) / 0j".
Decimal = Ошибка! Деление на 0 при вычислении "2 / 0".
Выражение : "1 2 3 +"
int = Ошибка! Некорректное выражение - в стеке остались элементы.
MyInt = Ошибка! Некорректное выражение - в стеке остались элементы.
float = Ошибка! Некорректное выражение - в стеке остались элементы.
complex = Ошибка! Некорректное выражение - в стеке остались элементы.
Decimal = Ошибка! Некорректное выражение - в стеке остались элементы.
Выражение : "1 2 + *"
int = Ошибка! Недостаточно операндов для вычисления.
MyInt = Ошибка! Недостаточно операндов для вычисления.
float = Ошибка! Недостаточно операндов для вычисления.
complex = Ошибка! Недостаточно операндов для вычисления.
Decimal = Ошибка! Недостаточно операндов для вычисления.