Функція eval() у Python: як відбувається динамічне виконання виразів
Завдяки цій публікації ви дізнаєтеся, навіщо Python потрібна вбудована функція 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() таїть у собі потенційну небезпеку, оскільки з її допомогою можна запускати будь-який рядковий код. При введенні даних без необхідного рівня валідації це може призвести до проблем у сфері безпеки. Наприклад, хакер може ввести довільний шкідливий код, який програма потім виконає.
Перед вами приклад неправильного використання функції:
dangerous_input = "import os; os.system('rm -rf /')" eval(dangerous_input) # Не треба так робити!!
У цьому фрагменті хакер намагається використати eval(), щоб запустити свій код на пристрої користувача.
Щоб мінімізувати ризик використання функції eval(), дотримуйтесь рекомендацій:
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 і виводиться на екран.
Аргумент 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 дозволяє контролювати, які змінні будуть доступні у виразі. Це робить виконання коду контрольованішим.
Аргумент 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() можна застосовувати в оцінці будь-яких висловів Python, крім операторів. Використання eval() особливо зручне, якщо потрібно динамічно оцінити вирази, коли інші методи або інструменти не підходять через брак часу. Давайте розглянемо, як використовувати eval() при оцінці булевих, математичних та загальних виразів Python.
Булеві вирази — це вирази у мові Python, здатні повертати значення типу bool (істина чи брехня). Це можуть бути порівняння, логічні операції та деякі інші вирази. Зазвичай вони використовуються в операторах if для перевірки істинності чи хибності певної умови.
Приклад використання eval() для оцінки булевих виразів:
# Строковий булевий вираз expression = "6 > 4 і 1 < 3" # Оцінка виразу за допомогою eval result = eval(expression) print(f"Результат булевого виразу '{expression}': {result}")
Пояснення:
expression: У цьому прикладі рядок “6 > 4 and 1 < 3” містить два логічні вирази, об’єднані оператором and. Перший вираз перевіряє, чи більше 6, ніж 4, а друге – чи менше 1, ніж 3.
Функція eval() виконує обчислення цього виразу та повертає результат типу bool. В даному випадку обидві частини виразу істинні, тому загальний результат буде True.
Функція 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, яка виводиться на екран.
Тепер, коли ви навчилися застосовувати 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.
# Отримуємо загальний вираз від користувача user_input = input("Введіть вираз: ") # Наприклад, "10 ** 2 + 5" # Оцінка виразу за допомогою eval result = eval(user_input) print(f"Результат виразу '{user_input}': {result}")
Пояснення:
Користувач може ввести будь-який коректний вираз Python, наприклад: “10 ** 2 + 5” (зведення в ступінь та додавання). Після того як eval() виконає вираз, отримуємо результат: 105.
Функція eval() може бути використана для оцінки різних виразів в Python, від простих математичних до складних логічних і рядкових операцій. Важливо пам’ятати, що при роботі з введеннями користувача слід застосовувати заходи безпеки, обмежуючи доступ до вбудованих функцій і глобальних змінних, щоб уникнути виконання шкідливого коду.
Резиденти Дія.City сплатили до бюджету понад 8 млрд грн податків в І кварталі 2025 року.…
У Китаї закликають офісних працівників не працювати надто багато — держава сподівається, що вільний час…
Експерти звертають увагу на тривожну тенденцію: люди все частіше використовують ChatGPT, щоб визначити місцезнаходження, зображене…
Компанія JetBrains випустила нову версію мультимовного середовища розробки IntelliJ IDEA 2025.1. Оновлена IDE отримала численні…
Платформа обміну миттєвими повідомленнями Discord впроваджує функцію перевірки віку за допомогою сканування обличчя. Зараз вона…
Wikipedia намагається захистити себе від тисяч різноманітних ботів-скрейперів, які сканують дані цієї платформи для навчання…