@kolyart2022

Как решить пример в Python, который находится как string в переменной?

Можно ли как-то решить пример в Python, который находится как string в переменной?
Примерно вот так:
anwser = "7 + 13"
  • Вопрос задан
  • 74 просмотра
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Тупой способ: использовать eval(), но это очень рискованно! Если данные приходят извни, атакующий может вписать туда почти любой питоновский код. Потом не плачь, что тебя не предупреждали.

Умный способ, на примере (-5 * 3) - 2:
1. Разбить строку на осмысленные токены : число, оператор и т.п. Для каждого токена хранить его тип и значение. Получим список в духе:
[('parenthesis', '('), ('operator', '-'), ('number', '5'), ('operator', '*'), ('number', '3'), ('parenthesis', ')'), ('operator', '-'), ('number', '2') ]

Тут ушли все пробелы.
2. Подправить унарные операторы. Операторы "+" и "-", следующие за началом строки, открывающей скобкой или другим оператором, являются унарными (с одним аргументом), а не бинарными (с двумя). Их стоит обозначить по другому, чтобы не путать. Получим такое (смотри на второй токен):
[('parenthesis', '('), ('operator', 'unary-'), ('number', '5'), ('operator', '*'), ('number', '3'), ('parenthesis', ')'), ('operator', '-'), ('number', '2') ]

3. Преобразовать из инфиксной нотации (2 + 3) в постфиксную (2 3 +). Для этого есть железнодорожный алгоритм Дейкстры, он гуглится. В постфиксной нотации всё решается куда проще, так как ей не нужны скобки. Наш пример запишется как 5 unary- 3 * 2 -
[('number', '5'), ('operator', 'unary-'), ('number', '3'), ('operator', '*'),  ('number', '2'), ('operator', '-')]

4. Решить пример. Алгоритм очень простой. У нас есть список аргументов, поначалу он пуст. Идём по списку токенов (в постфиксной нотации):
а. Если токен - число, поместить его в конец списка аргументов, перейти к следующему токену.
б. Если токен - унарный оператор, взять и удалить последний элемент из списка, применить к этому элементу оператор, результат добавить в конец списка.
в. Если токен - бинарный оператор, взять и удалить последние 2 элемента из списка, применить к ним оператор (не перепутай порядок аргументов!), результат добавить в конец списка.
Всё! Когда токены кончатся, у тебя в списке аргументов должно быть ровно одно число - это и будет ответ.
На нашем примере:
[('number', '5'), ('operator', 'unary-'), ('number', '3'), ('operator', '*'),  ('number', '2'), ('operator', '-')]

1. Число "5": список аргументов [ 5 ]
2. Унарный минус: берем 5 из списка, применяем оператор, кладем результат назад. Список аргументов [ -5 ]
3. Число "3": список аргументов [ -5, 3 ]
4. Оператор *: берем -5 и 3 из списка, применяем оператор, кладём результат назад. Список аргументов [ -15 ]
5. Число "2": список аргументов [ -15, 2 ]
6. Бинарный минус: берем -15 и 2 из списка, применяем оператор, кладём результат назад. Список аргументов [ -17 ]
Токены закончились, в списке одно число -17. Это ответ.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Kash_Tan
существует фунцкия eval
т.е.
result = eval(answer)

но eval - опасная функция, можешь загуглить почему, так что лучше использовать literal_eval из библиотеки ast, эта функция безопаснее

from ast import literal_eval
result = literal_eval(answer)


ну или просто сделать код, который будет все это вычислять
Ответ написан
@ppttzz
регулярным выражением отделить цифры от символов математических операций присвоив разным переменным
переведи в int('str') или float('str'), по условию смотря какой символ запусти нужную операцию
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы