Глава 23 · Ещё больше мини-проектов

Проект 23-1: Калькулятор с Tkinter

Экран, сетка кнопок и функция vychislit_vyrazhenie() — вот и весь калькулятор.

Проект 23-1: Калькулятор с Tkinter

Собираем настоящий калькулятор: экран сверху, кнопки с цифрами и знаками снизу. Идея та же, что и в тренажёре «Крестики-нолики» из главы 19 — сетка кнопок, каждая из которых вызывает одну и ту же функцию с разным аргументом:

sozdanie_knopok.py
KNOPKI = [
    ("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("/", 1, 3),
    ("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("*", 2, 3),
    # ...
]

for podpis, stroka, stolbec in KNOPKI:
    knopka = tk.Button(root, text=podpis,
                        command=lambda s=podpis: na_cifru_ili_znak_nazhali(s))
    knopka.grid(row=stroka, column=stolbec, sticky="we")
lambda s=podpis — почему нельзя просто lambda: ...(podpis)
Это тот же самый «капкан позднего связывания замыканий», что мы разбирали в главе 17: без s=podpis все кнопки запомнили бы одну и ту же, последнюю по циклу переменную podpis — и нажатие любой кнопки вставляло бы один и тот же символ.

Вычисляем выражение

Вместо того чтобы писать свой разбор арифметики, используем встроенную функцию eval() — но осторожно: проверяем, что в строке нет ничего, кроме цифр и знаков, и запрещаем доступ к встроенным функциям Python:

vychislenie.py
def vychislit_vyrazhenie(vyrazhenie):
    dopustimye_simvoly = set("0123456789+-*/(). ")
    if not vyrazhenie or not set(vyrazhenie) <= dopustimye_simvoly:
        return "Ошибка"
    try:
        return str(eval(vyrazhenie, {"__builtins__": {}}, {}))
    except (SyntaxError, ZeroDivisionError, ValueError):
        return "Ошибка"
Почему просто не написать eval(vyrazhenie)?
Обычный eval() выполнит любой Python-код, который ему передать — например, команду для удаления файлов. Проверка разрешённых символов и пустой словарь {"__builtins__": {}} не дают выражению сделать ничего, кроме простой арифметики.

Полный код: 📄 projects/tkinter/calculator/calculator.py

Практика в Jupyter Notebook
23-01-kalkulyator.ipynb · вычисления и последовательности нажатий
Открыть ноутбук →