Основные подходы к вычислению выражения из строки в Python

Раздел: Основы Python -> Математические вычисления

Основное решение и альтернативы

Самый простой способ вычислить выражение из строки - использовать функцию eval(). Она принимает строку с корректным Python-выражением и возвращает результат.

expr = "3 + 5 * 2"
result = eval(expr)
print(result)

Python решение примера (решение примера на python)

13

Python вычисление значения выражений (вычисление значения выражений в python)

Безопасность

Функция eval может выполнить произвольный код. Не рекомендуется использовать её с непроверенными данными от пользователя. Можно ограничить пространство имён с помощью пустого словаря: eval(expr, {"__builtins__": {}}), но это не даёт полной защиты.

Какие риски связаны с eval?

Злоумышленник может передать строку, удаляющую файлы. Например: "__import__('os').system('rm -rf /')". Даже при ограничении пространства имён существуют обходные пути. Поэтому для вычисления математических выражений от непроверенного источника лучше использовать специализированные библиотеки.

Как безопасно вычислить только литеральные структуры?

Модуль ast содержит функцию literal_eval, которая разбирает и вычисляет только Python-литералы (числа, строки, кортежи, списки, словари, множества, булевы значения, None). Арифметические операции не поддерживаются.

import ast
expr = "[1, 2, 3]"
result = ast.literal_eval(expr)
print(result, type(result))

вычисление функции в python (вычисление значения функции в python)

[1, 2, 3] <class 'list'>

Python вычисление корня (вычисление квадратного корня в python)

При попытке вычислить "1+2" возникает ValueError: malformed node or string. Этот метод подходит только для разбора статических данных, не содержащих операторов.

Как вычислить выражение с тригонометрическими функциями?

Библиотека SymPy предназначена для символьных вычислений. Она позволяет безопасно вычислять математические выражения, включая функции из модуля math. Для этого используется sympy.sympify или sympy.parsing.sympy_parser.parse_expr.

import sympy as sp
expr = "sin(pi/2) + cos(0)"
result = sp.sympify(expr)
print(result)

Python формула (написание математических формул в python)

1.0

решение системы уравнений python (решить систему уравнений в python)

SymPy медленнее для простых численных вычислений, но предоставляет возможность работы с символами, упрощениями, дифференцированием и т.д. Если требуется только численный результат, возможно, стоит рассмотреть eval с ограничениями или numexpr.

Как быстро вычислить выражение над массивами чисел?

Библиотека numexpr оптимизирована для быстрых поэлементных операций над массивами NumPy. Она компилирует выражение во внутренний байт-код и выполняет его параллельно.

import numexpr as ne
import numpy as np
x = np.arange(1, 5)
expr = "x**2 + 2*x + 1"
result = ne.evaluate(expr)
print(result)

Python вычислить строку (вычисление выражения из строки в python)

[ 4  9 16 25]

возвести в квадрат python (возведение числа в квадрат в python)

Numexpr не поддерживает все функции Python, только набор математических операций и функций (sin, cos, exp и др.). Если выражение содержит вызовы произвольных функций, использование numexpr приведёт к ошибке.

Как написать собственный парсер для простых арифметических выражений?

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

import re
def safe_eval(expr):
    # разрешены только цифры, операторы и скобки
    if re.match(r'^[0-9+\-*/().\s]+$', expr):
        return eval(expr, {"__builtins__": {}}, {})
    else:
        raise ValueError("Недопустимые символы")
print(safe_eval("2+3*4"))

площадь python (вычисление площади в python)

14

Регулярное выражение может быть обмануто (например, числа с плавающей точкой, пробелы). Для более надёжного парсинга стоит использовать грамматики. Этот подход требует больше усилий, но может быть оправдан в специфических случаях.

- решить уравнение python (решение уравнения в python)
- Python квадратное уравнение (решение квадратного уравнения в python)

Расширенные примеры вычисления строковых выражений

Пример 1: eval с ограниченным пространством имён и поддержкой math

Пример
import math
# разрешаем только math и None
allowed_globals = {"__builtins__": {}, "math": math, "None": None}
expr = "math.sin(math.pi/2) + math.sqrt(16)"
result = eval(expr, allowed_globals)
print(result)
5.0

Пояснение

В словарь allowed_globals добавлены только необходимые функции. Это частично повышает безопасность, но всё равно не защищает от атак через __class__ и рефлексию.

Пример 2: sympy для символьного дифференцирования

Пример
import sympy as sp
x = sp.Symbol('x')
expr_str = "x**3 + 2*x**2 - 5*x + 1"
expr = sp.sympify(expr_str)
derivative = sp.diff(expr, x)
print("Производная:", derivative)
print("Значение при x=2:", derivative.subs(x, 2))
Производная: 3*x**2 + 4*x - 5
Значение при x=2: 15

Пример 3: numexpr с условными выражениями

Пример
import numexpr as ne
import numpy as np
x = np.array([-1, 0, 1, 2, 3])
expr = "where(x > 0, x**2, 0)"
result = ne.evaluate(expr)
print(result)
[0 0 1 4 9]

Функция where из numexpr работает как поэлементное условие. Это позволяет компактно записывать ветвления.

Пример 4: ручной парсер с использованием pyparsing

Пример
from pyparsing import Word, nums, oneOf, Forward, Group, Suppress
import operator

# определение грамматики целых чисел
integer = Word(nums).setParseAction(lambda t: int(t[0]))
# операторы
op = oneOf("+ - * /")
# грамматика выражения (рекурсивная)
expr = Forward()
term = Group(integer + op + expr) | integer
expr << term
# пример использования
def eval_parsed(tokens):
    if isinstance(tokens, int):
        return tokens
    left, op, right = tokens[0]
    left_val = eval_parsed(left)
    right_val = eval_parsed(right)
    ops = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.truediv}
    return ops[op](left_val, right_val)

parsed = expr.parseString("3+5*2")[0]
print(eval_parsed(parsed))
13

Этот пример демонстрирует, как построить собственный безопасный парсер с поддержкой приоритета операций (рекурсивный спуск). В реальном коде потребуется более сложная грамматика для учёта скобок и унарных минусов.

Вычисление выражения из строки в Python - comments

En
Python вычислить строку (python)