БэкендPython

Как сделать калькулятор на Python: кнопки, операции и готовое окно

Собираем оконный калькулятор на Python и Tkinter без eval: два числа, четыре операции, обработка ошибок и проверка результата.

Кодик

Автор

5 мин чтения

Калькулятор можно собрать на встроенном Tkinter без внешних библиотек и без eval. Вы введёте два числа, выберете действие и получите ответ в окне. Ошибка ввода и деление на ноль не уронят программу.

Учебный калькулятор хорош тем, что здесь встречаются сразу три слоя: математика, проверка ввода и интерфейс. Если смешать их в одной функции, код быстро превратится в лес из if. Мы отделим функцию calculate от окна, поэтому её можно проверить без кликов.

1Читаем

Превращаем два поля в float и ловим ошибку ввода.

2Считаем

Сопоставляем знак с функцией из operator, не используем eval.

3Показываем

Обновляем одну метку и оставляем окно готовым к следующему расчёту.

Из каких частей состоит калькулятор

В окне будут два Entry, Combobox со знаками операций, кнопка и Label для ответа. Нажатие не должно знать, как именно считается сумма или частное. Кнопка только передаёт данные функции и показывает ответ.

ЧастьОбъектЗадача
Вводttk.EntryХранит текст до проверки
Операцияttk.ComboboxОграничивает выбор четырьмя знаками
Расчётcalculate()Возвращает число или понятную ошибку
ВыводStringVarМеняет текст без пересоздания Label

Граница проходит между StringVar и calculate: до неё лежит пользовательский текст, после неё только числа и известная операция.

Путь одного расчёта
От текста к ответу. Ошибка перехватывается до обновления Label

Сначала соберите минимальный сценарий. Не добавляйте оформление, хранение и дополнительные режимы одновременно. Добейтесь одного правильного прохода от входных данных до результата, а затем проверяйте каждое улучшение отдельно.

Пишем расчёт и окно Tkinter

Модуль operator даёт готовые функции add, sub, mul и truediv. Мы свяжем их со знаками в словаре. Это убирает цепочку условий и не позволяет выполнить произвольную строку как Python-код.

import operator
import tkinter as tk
from tkinter import ttk

OPERATIONS = {
    "+": operator.add,
    "-": operator.sub,
    "×": operator.mul,
    "÷": operator.truediv,
}

def calculate(left: str, right: str, sign: str) -> float:
    a = float(left.replace(",", "."))
    b = float(right.replace(",", "."))
    if sign == "÷" and b == 0:
        raise ValueError("На ноль делить нельзя")
    return OPERATIONS[sign](a, b)

root = tk.Tk()
root.title("Калькулятор")
root.resizable(False, False)

left = tk.StringVar(value="12")
right = tk.StringVar(value="3")
sign = tk.StringVar(value="+")
answer = tk.StringVar(value="Ответ появится здесь")

frame = ttk.Frame(root, padding=24)
frame.grid()
ttk.Entry(frame, textvariable=left, width=12).grid(row=0, column=0)
ttk.Combobox(frame, textvariable=sign, values=list(OPERATIONS),
             state="readonly", width=4).grid(row=0, column=1, padx=8)
ttk.Entry(frame, textvariable=right, width=12).grid(row=0, column=2)

def show_result() -> None:
    try:
        value = calculate(left.get(), right.get(), sign.get())
        answer.set(f"Результат: {value:g}")
    except (ValueError, KeyError):
        answer.set("Проверьте числа и операцию")

ttk.Button(frame, text="Посчитать", command=show_result).grid(
    row=1, column=0, columnspan=3, sticky="ew", pady=16
)
ttk.Label(frame, textvariable=answer).grid(row=2, column=0, columnspan=3)
root.mainloop()
Что должно работать после первого запуска

Сумма, разность и произведение считаются одной функцией. Запятая в дроби заменяется на точку до float. Деление на ноль даёт текст в окне, а не traceback. Кнопка работает повторно без перезапуска.

eval или словарь
Для четырёх операций выбор однозначен. Сравнение показывает, какой вариант легче поддерживать и проверять.

Почему здесь не нужен eval

Функция eval превращает строку в выполняемое выражение. Для учебного калькулятора это лишнее и опасное расширение возможностей. Нам известны ровно четыре допустимых действия, поэтому словарь точнее описывает правила программы.

СитуацияЧто происходитЧто видит пользователь
12 + 3Вызов operator.addРезультат: 15
2,5 × 4Замена запятой, затем mulРезультат: 10
10 ÷ 0Явная проверка до truedivНа ноль делить нельзя
abc + 1float вызывает ValueErrorПроверьте числа

Обрабатывайте ошибку там, где есть понятный способ её показать. calculate может выбросить ValueError, а show_result переводит его в короткую фразу в Label. Так ядро остаётся удобным для тестов, а интерфейс не показывает внутренние детали Python.

Смотрите на состояние, а не только на красивый экран. Перезагрузка, повторный клик, пустой ввод и медленный ответ часто открывают ошибки, которые не видны в идеальном демонстрационном проходе.

Практика: проверяем границы

Не ограничивайтесь примером 2 + 2. Полезные тесы находят границы: ноль, отрицательное число, дробь с запятой, пустое поле и многократное нажатие. Важен не один красивый кадр, а стабильная работа всех четырёх операций.

Проверка своими руками
  1. Запустите python calculator.py и посчитайте 12 + 3.
  2. Проверьте вычитание и умножение с отрицательным числом.
  3. Введите 2,5 и 4, выберите умножение.
  4. Поделите 10 на 0 и убедитесь, что окно не закрылось.
  5. Очистите одно поле и нажмите кнопку ещё раз.
  6. Измените начальные значения StringVar и перезапустите файл.
Готово, если выполняются все пункты

Все четыре операции возвращают ожидаемые числа. Неверный ввод и ноль в знаменателе не закрывают окно. После ошибки можно исправить поле и сразу посчитать снова. Код не выполняет текст пользователя через eval.

Четыре границы проекта
Проверьте их до оформления. Пройдите все четыре сценария перед публикацией проекта.

Доводим калькулятор до готового вида

Визуальный слой можно улучшать после того, как расчёт стал надёжным. Добавьте отступы, фокус на первом поле и клавишу Enter. Не пытайтесь сразу повторить системный калькулятор с памятью и скобками. Текущий проект уже закрывает главную учебную цель: данные проходят от интерфейса к чистой функции и обратно.

eval вместо словаря

Программа получает лишнюю возможность выполнять текст. Оставьте явный набор операций.

except без типа

Широкий except скроет опечатку в коде. Ловите только ValueError и KeyError.

Деление без проверки

Ноль во втором поле должен дать понятное сообщение.

Логика внутри кнопки

Вынесите расчёт в calculate, иначе его сложно проверять.

Сверьтесь с первичным источником. Поведение используемых функций и ограничения примера проверяйте по документацией Python по Tkinter. Документация особенно важна, когда меняются версии, политика платформы или формат ответа API.

Что получится в итоге

Готовый результат проекта: Как сделать калькулятор на Python: кнопки, операции и готовое окно
Готовое окно показывает два числа, выбор операции, кнопку и ответ без лишних экранов.

Короткие ответы
Нужно ли ставить Tkinter через pip?

Обычно нет. Tkinter входит в стандартную библиотеку Python, хотя в некоторых Linux-дистрибутивах GUI-пакет ставят через системный менеджер.

Почему не используем eval?

Нам нужны четыре заранее известные операции. Словарь функций точнее и безопаснее.

Как принять дробь с запятой?

Заменить запятую на точку перед вызовом float.

Как понять, что проект готов?

Он повторяет целевой сценарий несколько раз подряд, понятно реагирует на ошибочный ввод и не теряет состояние при обычных действиях.

Можно ли копировать код целиком?

Можно как стартовую точку, но сначала замените значения из примера, затем запустите проект по шагам. Если вы не можете объяснить одну строку, её лучше разобрать до следующего шага.

Превратите одну функцию в маленькое приложение

Функции, словари и исключения можно закрепить в курсе Python. Если строка и число снова конфликтуют, откройте разбор TypeError.

Следующий проект можно взять из генератора паролей или игры камень, ножницы, бумага. В разделе «Практика» Кодика такой файл можно запускать прямо с телефона.