Don’t learn to code. Code to learn!
Введение в Python
- Python — Обзор
- Основы синтаксиса Python
- Операторы в Python
- Типы данных в Python
- Условные конструкторы в Python
- Циклы в Python
- Функции в Python
- Функциональное программирование в Python
- ООП в Python
- Модули в Python
- Работа с файлами в Python
- Обработка исключительных ситуаций в Python
Рассмотрим пример создания графического интерфейса (GUI) на Python. В качестве «жертвы» напишем простенькую программу — решатель квадратных уравнений. Наше задание мы разобъем на несколько частей.
Часть первая: функция решения квадратного уравнения.
Напомним, что квадратным является уравнение вида:
Есть несколько способов решить квадратное уравнение, мы выберем решение через дискриминант.
Используя эту формулу мы можем вывести решение. Если дискриминант больше или равен нулю, то корни уравнения высчитываются по формуле:
Как создать графический интерфейс на Python с нуля
Если же дискриминант меньше нуля, то уравнение не имеет решений.
Превратим данные формулы в код:
def solver(a,b,c): «»» Решает квадратное уравнение и выводит отформатированный ответ «»» # находим дискриминант D = b*b — 4*a*c if D >= 0: x1 = (-b + sqrt(D)) / (2*a) x2 = (-b — sqrt(D)) / (2*a) text = «The discriminant is: %s n X1 is: %s n X2 is: %s n» % (D, x1, x2) else: text = «The discriminant is: %s n This equation has no solutions» % D return text
Чтобы все работало не забудьте импортировать функцию sqrt из модуля math.
from math import sqrt
Поскольку мы будем выводить результат в специально созданном виджете — мы сразу же вставляем полученный ответ в отформатированную строку и возвращаем ее.
Теперь пора переходить к созданию графической оболочки для нашего приложения.
Часть вторая: создаем GUI для программы
Для простоты будем создавать GUI встроенными средствами Python, поэтому импортируем все из библиотеки Tkinter:
from Tkinter import *
В Python версии 3.х название модуля следует писать с маленькой буквы — tkinter.
Далее создаем само окно и размещаем на нем необходимые виджеты:
# родительский элемент root = Tk() # устанавливаем название окна root.title(«Quadratic calculator») # устанавливаем минимальный размер окна root.minsize(325,230) # выключаем возможность изменять окно root.resizable(width=False, height=False) # создаем рабочую область frame = Frame(root) frame.grid() # поле для ввода первого аргумента уравнения (a) a = Entry(frame, width=3) a.grid(row=1,column=1,padx=(10,0)) # текст после первого аргумента a_lab = Label(frame, text=»x**2+»).grid(row=1,column=2) # поле для ввода второго аргумента уравнения (b) b = Entry(frame, width=3) b.grid(row=1,column=3) # текст после второго аргумента b_lab = Label(frame, text=»x+»).grid(row=1, column=4) # поле для ввода третьего аргумента уравнения (с) c = Entry(frame, width=3) c.grid(row=1, column=5) # текст после третьего аргумента c_lab = Label(frame, text=»= 0″).grid(row=1, column=6) # кнопка решить but = Button(frame, text=»Solve»).grid(row=1, column=7, padx=(10,0)) # место для вывода решения уравнения output = Text(frame, bg=»lightblue», font=»Arial 12″, width=35, height=10) output.grid(row=2, columnspan=8) # запускаем главное окно root.mainloop()
Если вы в точности повторили указанный код, то после запуска скрипта у вас получится примерно следующее окно:
Красивый графический интерфейс на Python | Все Фишки DearPyGui
Отлично, программа работает. Осталось объяснить Python как связать эти две части.
Часть третья: объединяем все воедино
Задача перед нами стоит следующая — написать функцию, которая будет брать числа из полей для ввода, передавать их функции решения квадратного уравнения и выводить результат в поле для вывода. Конечно, все это можно реализовать в одной функции, но лучше разделить на несколько:
Функция вставки информации:
def inserter(value): «»» Inserts specified value into text widget «»» output.delete(«0.0″,»end») output.insert(«0.0»,value)
Функция inserter предельно проста: очищает поле для ввода и вставляет туда переданный ей аргумент value.
Напишем функцию обработки введенной информации. Назовем ее handler:
def handler(): «»» Get the content of entries and passes result to the output area «»» try: # make sure that we entered correct values a_val = float(a.get()) b_val = float(b.get()) c_val = float(c.get()) inserter(solver(a_val, b_val, c_val)) except ValueError: inserter(«Make sure you entered 3 numbers»)
В зависимости от данных введенных в поля для ввода передает функции inserter либо результат решения уравнения, либо сообщение о неверно введенных данных.
Чтобы все работало, следует изменить строку создания виджета Button следующим образом:
but = Button(frame, text=»Solve», command=handler).grid(row=1, column=7, padx=(10,0))
Теперь можно спокойно пользоваться нашей программой:
![]() |
![]() |
Дискриминант больше нуля | Дискриминант равен нулю |
![]() |
![]() |
Дискриминант меньше нуля. Решений нет | Введены не все аргументы |
Часть четвертая: необязательная
Можно добавить немного удобства для нашей программы. Проблема в том, что каждый раз вводя новые значения нам приходится удалять старые, что не очень комфортно. Напишем функцию, которая будет очищать поле для ввода после клика по нему.
def clear(event): «»» Clears entry form «»» caller = event.widget caller.delete(«0», «end»)
Таким образом мы очищаем виджет, вызвавший данную функцию. Чтобы все работало, добавьте следующие строки после создания виджетов, но до размещения. Например, после строки a = Entry(. , но до строки a.grid(.
a.bind(«», clear) b.bind(«», clear) c.bind(«», clear)
Готово. Программа работает, Вы великолепны!
Исходный код калькулятора квадратных уравнений с GUI на GitHub
- Пятнашки на Python
- Паттерны проектирования в Python
- Множествeнное наследование в Python
- Абстрактные классы в Python
- Сапер на Python
Источник: www.pythonicway.com
Давайте напишем командную оболочку Linux
Всем привет! Хочу поделиться своим опытом написания собственной командной оболочки Linux используя Posix API, усаживайтесь поудобнее.
Что должна уметь наша командная оболочка
- Запуск процессов в foreground и background режиме
- Завершение background процессов
- Поддержка перемещения по директориям
Как устроена работа командной оболочки
- Считывание строки из стандартного потока ввода
- Разбиение строки на токены
- Создание дочернего процесса с помощью системного вызова fork
- Замена дочернего процесса на необходимый с помощью системного вызова exec
- Ожидание завершения дочернего процесса (в случае foreground процесса)
Немного про системный вызов fork()
Простыми словами системный вызов fork создает полный клон текущего процесса, отличаются они лишь своим идентификатором, т. е. pid .
#include #include #include int main() < pid_t pid = fork(); if (pid == 0) < printf(«I’m child process!n»); >else < printf(«I’m parent process!n»); wait(NULL); >return 0; >
Что выведет данная программа:
I’m parent process!
I’m child process!
Что же произошло? Системный вызов fork создал клон процесса, т. е. теперь мы имеем родительский и дочерний процесс.
Чтобы отличить дочерний процесс от родительского в коде достаточно сделать проверку. Если результат функции fork равен 0 — мы имеем дело с дочерним процессом, если нет — с родительским. Это не означает, что в операционной системе id дочернего процесса равен 0 .
Причем, порядок выполнения дочернего и родительского процесса ничем не задекларирован. Все будет зависеть от планировщика операционной системы. Поэтому в конце блока родительского процесса добавлена строчка wait(NULL) , которая дожидается окончания дочернего процесса.
Подробнее про exec()
В документации есть различные вариации системного вызова exec , но они отличаются только способом передачи токенов в параметры функции, смысл от этого не изменяется.
Системный вызов exec заменяет текущий процесс сторонним. Естественно, сторонний процесс задается через параметры функции.
#include #include #include #include int main() < pid_t pid = fork(); if (pid == 0) < execlp(«ls», «ls», «-l», NULL); exit(1); >else < waitpid(pid, NULL, 0); >return 0; >
Что выведет данная программа
total 16
-rwxr-xr-x 1 runner runner 8456 Jan 13 07:33 main
-rw-r—r— 1 runner runner 267 Jan 13 07:33 main.c
Родительский процесс как обычно ожидает завершения дочернего процесса. В это время после системного вызова exec происходит замена дочернего процесса на консольную утилиту ls , она была взята для примера.
Можно сказать мы реализовали простую командную оболочку, вся логика заключается именно в этом.
Перейдем к полноценной реализации
Часть 1. Чтение строки с консоли
Изначально нам надо уметь считывать строку из командной строки. Думаю, с этим не возникнет сложностей.
char* readline() < char* line = NULL; size_t size = 0; ssize_t str_len; // Reading line from stdin if ((str_len = getline(size, stdin)) == -1) < // Logging all errors except Ctrl-D — terminal shutdown if (errno != 0) < printf(«[ERROR] Couldn’t read from stdinn»); >free(line); printf(«n»); return NULL; > // Remove useless n symbol if exists if (line[str_len — 1] == ‘n’) < line[str_len — 1] = ‘