Функция eval() в Python: как происходит динамическое выполнение выражений
Благодаря этой публикации вы узнаете, зачем в Python нужна встроенная функция eval(), и как ее максимально эффективно использовать. Помимо теории, вы ознакомитесь с примерами кода, которые демонстрируют практическое применение этой функции.
Зачем в Python нужна функция eval()
Функция eval() интерпретирует строку как код. Она используется для вычисления строк, содержащих выражения, а затем возвращает результат их выполнения. Благодаря этой функции можно динамически оценивать строчные выражения. Это делает eval() эффективным инструментом, но с ним нужно обращаться осторожно.
Как работает eval()
Давайте познакомимся с синтаксисом eval():
eval(expression, globals=None, locals=None)
В данном примере expression является строкой, в которой мы видим выражения globals и locals — это необязательные аргументы, отражающие наличие глобальной и локальной области видимости.
Во избежание путаницы стоит отметить, что для динамического выполнения кода также применять функцию exec(). Различие между ней и eval() состоит в том, что eval() способна выполнять только выражения, а функция exec() может выполнять практически любой фрагмент кода.
Теперь стоит ознакомиться с практическим использованием eval() в Python:
x = 3 code = "x + 8" result = eval(code) print(result) # Вывод: 11
Здесь функция eval() выполняет вычисление выражение x + 8, а print() отображает это значение.
А сейчас пример с интерактивным вводом данных:
user_input = input("Напишите выражение: ") # Пользователь пишет на клавиатуре "20 + 30" result = eval(user_input) print(result) # Вывод: 50
В данном примере eval() обрабатывает ввод выражения с последующим вычислением готового результата.
Что важно помнить при использовании eval()
Функция eval() таит в себе потенциальную опасность, поскольку с ее помощью можно запускать любой строчный код. При вводе данных без необходимого уровня валидации, это может привести к проблемам в сфере кибербезопасности. К примеру, хакер может ввести произвольный опасный код, который приложение затем выполнит.
Перед вами пример неправильного использования функции:
dangerous_input = "import os; os.system('rm -rf /')" eval(dangerous_input) # Не нужно так делать!!
В этом фрагменте хакер пытается использовать eval() чтобы запустить свой код на устройстве пользователя.
Как безопасно применять eval()
Чтобы минимизировать риск при использовании функции eval(), придерживайтесь рекомендаций:
- Создавайте ограничения доступа к глобальным и локальным переменным, передавая безопасные словари.
- По возможности избегайте использования eval() в программном коде. Для вычисления математических выражений можно использовать безопасные библиотеки, такие как ast.literal_eval(), или специализированные библиотеки для работы с математикой, такие как sympy.
Аргументы, используемые в функции eval()
1. Аргумент Expression
Expression — это совокупность элементов выражения. К ним относятся литералы, наименования, доступы к атрибутам, операторы или вызовы функций. Все они возвращают значение.
При работе eval() содержание expression понимается как выражение. Функция отображает результат после того, как оценит переданную при вводе строку. Перед этим eval() делает парсинг и компилирование кода, оценку выражение и возвращение результатом этой оценки.
Само по себе название expression говорит о том, что функция взаимодействует только с выражениями, а не с другими конструкциями. Вы сами можете в этом убедиться, если попытаетесь передать блок кода вместо выражения. В итоге вы увидите исключение SyntaxError.
Пример использования аргумента expression:
# Математическое строчное выражение expression = "10 * (6 + 9)" # Выполняем выражение с помощью eval result = eval(expression) print(f"Результат выражения '{expression}': {result}")
Пояснение:
expression: В данном примере мы передали строку “10 * (6 + 9)” в виде выражения. Функция eval() вычисляет результат этого математического задания. Вычисление даёт результат 150. Затем этот результат сохраняется в переменной result, и выводится на экран.
2. Аргумент globals
Аргумент globals ограничивает доступ к глобальным переменным, переопределяет их и создает ограниченную среду для выполнения выражений. Это может быть полезно для тестирования, вычислений или обработки выражений без влияния на рабочий код программы.
Пример работы аргумента globals:
# Определим переменные globals x = 10 y = 20 # Функция eval с передачей кастомного словаря переменных globals expr = "x + y" custom_globals = {"x": 5, "y": 15} # Выполнение с ограниченным доступом к переменным globals result = eval(expr, custom_globals) print(result) # Вывод: 20 # Попробуем вызвать eval с использованием обычных переменных globals result = eval(expr) print(result) # Вывод: 30
Пояснение:
З вышеуказанном примере мы определили переменные x = 10 и y = 20 в глобальной области видимости.
Строка expr = “x + y” содержит выражение, которое нам нужно вычислить.
В первом вызове eval() мы передаем кастомный словарь custom_globals, где значения для x и y изменены на 5 и 15. В итоге eval() рассчитывает сумму этих новых значений и показывает 20.
Во втором вызове eval() выполняется без кастомного словаря, используя оригинальные глобальные значения x = 10 и y = 20. Таким образом, использование аргумента globals позволяет контролировать, какие переменные будут доступны в выражении. Это делает выполнение кода более контролируемым.
3. Аргумент locals
Аргумент locals дает возможность задать локальную область видимости, которая затем используется при выполнении выражения. Это позволяет контролировать, какие локальные переменные и функции доступны внутри выражения. Аргумент locals используется вместе с globals для определения контекста, в котором будет выполняться выражение.
Пример использования аргумента locals:
# Определяем переменные globals x = 10 y = 20 # переменные locals, которые передаются в eval local_vars = {"x": 5, "y": 15, "z": 30} # Строка выражения expression = "x + y + z" # Применяем eval с передачей локальных переменных result = eval(expression, globals(), local_vars) print(f"Результат выражения '{expression}' с локальными переменными: {result}")
Пояснение:
Хотя в данном коде можно видеть глобальные переменные x = 10 и y = 20, они не будут использоваться, потому что мы передаем свои локальные переменные.
Мы создаем словарь local_vars с локальными переменными x = 5, y = 15 и z = 30. Эти переменные будут доступны только внутри вызова eval().
expression: Строка “x + y + z” будет интерпретироваться как выражение, которое использует локальные значения x, y и z из словаря local_vars.
eval(): Вызов eval() выполняется с глобальной областью видимости (через globals(), которая возвращает текущие глобальные переменные) и локальной областью видимости (через local_vars).
Результат: Значения переменных x = 5, y = 15 и z = 30 суммируются,. На выводе получаем результат 50.
Таким образом, используя аргумент locals, можно ограничить или поменять локальные переменные, которые будут применяться только внутри функции eval(). Это очень полезно, когда требуется передать временные или специфичные для конкретного вызова переменные, не затрагивая при этом глобальные.
Как оценивать выражения, используя eval()
Функцию eval() можно применять при оценке любых выражений Python, за исключением операторов. Использование eval() особенно удобно, если требуется динамически оценить выражения, когда другие методы или инструментов не подходят по причине нехватки времени. Давайте рассмотрим, как использовать eval() при оценке булевых, математических и общих выражений Python.
1. Булевы выражения
Булевы выражения — это выражения в языке Python, способные возвращать значения типа bool (истина или ложь). Это могут быть сравнения, логические операции и некоторые другие выражения. Обычно они используются в операторах if для проверки истинности или ложности определенного условия.
Пример использования eval() для оценки булевых выражений:
# Строчное булевое выражение expression = "6 > 4 and 1 < 3" # Оценка выражения с помощью eval result = eval(expression) print(f"Результат булевого выражения '{expression}': {result}")
Пояснение:
expression: В этом примере строка “6 > 4 and 1 < 3” содержит два логических выражения, объединенных оператором and. Первое выражение проверяет, больше ли 6, чем 4, а второе — меньше ли 1, чем 3.
Функция eval() выполняет вычисление этого выражения и возвращает результат типа bool. В данном случае, обе части выражения истинны, поэтому общий результат будет True.
2. Математические выражения
Функция eval() может применяться для вычисления строчных математических выражений. Она очень удобна при вводе выражений пользователем. Давайте взглянем на пример, как при помощи eval() можно оценить математические выражения:
# Строчное математическое выражение expression = "4 + 6 * (1 - 7)" # Оценка выражения через eval result = eval(expression) print(f"Результат выражения '{expression}': {result}")
Пояснение:
expression: Строка “4 + 6 * (1 – 7)” содержит математическое выражение с операторами сложения, умножения и скобками.
Функция eval() выполняет вычисление этого выражение. Строка интерпретируется как обычное математическое выражение: сначала вычисляется выражение в скобках (1 – 7) = -6, затем умножение 6* (-6) = -36, и в конце добавляется 4 + (-36) = -32.
Вычисленный результат сохраняется в переменной result, которая выводится на экран.
3. Общие выражения
Теперь, когда вы научились применять eval() с булевыми и математическими выражениями, настало время овладеть теорией использования eval() с общими выражениями Python. Это любые выражения, способные возвращают значения. Давайте посмотрим фрагмент кода, где eval() используется для оценки общих выражений.
Оценка выражений, содержащих строки и списки:
# Общее выражение, работающее со списком и строкой expression = "'Hello' + ' ' + 'World' + '!'" # Оценка выражения result = eval(expression) print(f"Результат выражения '{expression}': {result}")
Пояснение: выражение складывает строки. Получаем строку: ‘Hello World!’.
Оценка сложных выражений с логическими операциями и списками:
# Сложное выражение с использованием списка и логического выражения expression = "len([1, 2, 3]) == 3 and (5 > 3)" # Оценка выражения с помощью eval result = eval(expression) print(f"Результат выражения '{expression}': {result}")
Пояснение:
- Выражение включает вычисление длины списка [1, 2, 3], проверку равенства и логическую операцию and.
- Результатом выполнения будет логическое значение: True, так как длина списка действительно равна 3 и 5 > 3 также истина.
Оценка выражений с вызовами функций:
# Определяем функцию def multiply(a, b): return a * b # Общее выражение, использующее вызов функции expression = "multiply(4, 5)" # Оценка выражения с передачей функции через globals() result = eval(expression, {"multiply": multiply}) print(f"Результат выражения '{expression}': {result}")
Пояснение:
Выражение использует вызов функции multiply(4, 5), которая возвращает произведение двух чисел.
Мы передаем функцию multiply в глобальные переменные при вызове eval(), чтобы она была доступна для вычисления.
Результатом будет значение 20.
4. Пример с пользовательским вводом
# Получаем общее выражение от пользователя user_input = input("Введите выражение: ") # Например, "10 ** 2 + 5" # Оценка выражения с помощью eval result = eval(user_input) print(f"Результат выражения '{user_input}': {result}")
Пояснение:
Пользователь может ввести любое корректное выражение Python, например: “10 ** 2 + 5” (возведение в степень и сложение). После того, как eval() выполнит выражение, получаем результат: 105.
Заключение
Функция eval() может быть использована для оценки самых различных выражений в Python, от простых математических до сложных логических и строковых операций. Важно помнить, что при работе с пользовательскими вводами нужно применять меры безопасности, ограничивая доступ к встроенным функциям и глобальным переменным, чтобы избежать выполнения вредоносного кода.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: