Программирование на языке Python: год 1

Введение. Объекты. Переменные. Основы ввода и вывода данных.

Слайды

Основные определения

Интерпретатор

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

IDLE (читается — айдл)

(Integrated Development and Learning Environment) — это интегрированная среда разработки и обучения на языке Python.

Данные в языке Python представлены в форме объектов.

Каждый объект имеет идентификатор, тип и значение.

Литерал

Форма записи для «фиксированного» представления значения объекта. Примеры литералов: 42, 4.2, "Hello, World!".

Идентификатор

Однозначно идентифицирует объект. Его можно считать адресом области в памяти компьютера, где хранится объект.

Тип данных

Тип определяет возможные значения и их смысл, операции, а также способы хранения значений типа.

Переменная

Именованная ссылка на конкретный объект.

Оператор присваивания связывает переменную и объект. Пример:

>>> x = 5

Первую привязку переменной к объекту в программе называем определением и инициализацией переменной.

Изученные средства языка

print(a)
print(a, b, c)

Функция принимает на вход объекты, преобразует их в строки и выводит в стандартный поток вывода.

Функция print может принимать дополнительные параметры, с ними мы познакомимся далее в курсе.

Примеры использования:

# Функция может принимать литералы…
print(42)
print("answer")

# … объекты
answer = 42
print(answer)

# …строки формата
print(f"The answer is {answer}")

import math.pi

# Вывод числа π с 4 знаками после запятой
print(f"Pi = {math.pi:.4f}")
input(prompt)

Выводит в стандартный поток вывода приглашение prompt, а затем считывает введенные пользователем данные и возвращает строку.

Примеры использования в IDLE:

>>> name = input("What is your name? ")
What is your name? James
>>> name
'James'

Пример ввода целых чисел:

a = int(input("a = "))
b = int(input("b = "))
s = a + b
print(f"{a} + {b} = {s}")
type(object)

Возвращает тип объекта object.

Примеры использования:

>>> type(42)
<class 'int'>
>>> type(42.0)
<class 'float'>
>>> type("Python")
<class 'str'>
int(x)

Принимает число или строку и возвращает целое число со знаком.

Примеры использования:

>>> int("42")
42
>>> int(42.5)
42
float(x)

Принимает число или строку и возвращает число с плавающей точкой.

Примеры использования:

>>> float("42")
42.0
>>> float("42.5")
42.5
>>> float(42)
42.0

О важности имен переменных

Что делает этот код?

import math


a = int(input('a: '))
b = int(input('b: '))

c = int(input('c: '))
d = int(input('d: '))

e = math.sqrt((c - a) ** 2 + (d - b) ** 2)

print(f"e: {e:.4f}")

Ответить на вопрос затруднительно. Можно рассказать о том, что происходит в каждой строчке: какие функции вызываются, какие операции выполняются, но смысл кода может оставаться неясным. Приложение ожидает на вход четыре каких-то числа, выводит какое-то новое число. Понять смысл такого кода может оказаться непросто из-за неудачного выбора имен переменных: a, b, c, d, e. Такие имена легко печатать, но сложно помнить смысл, спрятанный за ними.

Переименуем наши переменные и изменим приглашения для ввода:

import math


point1_x = int(input('Point 1 x: '))
point1_y = int(input('Point 1 y: '))

point2_x = int(input('Point 2 x: '))
point2_y = int(input('Point 2 y: '))

distance = math.sqrt((point2_x - point1_x) ** 2 + (point2_y - point1_y) ** 2)

print(f"Distance: {distance:.4f}")

Смысл кода сразу же становится понятен: приложение ожидает на вход координаты двух точек и вычисляет расстояние между ними. Можно не помнить формулы или не понимать каждой строки кода — удачно выбранные имена переменных помогут сориентироваться.

Задачи

  1. Реализовать приложение для вычисления периметра и площади прямоугольника. Приложение запрашивает у пользователя два целых числа — длины сторон прямоугольника. Пример работы приложения:

    Input a: 5
    Input b: 4
    
    P = 18
    S = 20
    
  2. Напишите программу, которая считывает значения двух переменных a и b, затем меняет их значения местами (то есть в переменной a должно быть записано то, что раньше хранилось в b, а в переменной b записано то, что раньше хранилось в a). Затем выведите значения переменных.

  3. Напишите программу, которая приветствует пользователя, выводя слово Hello, введенное имя и знаки препинания по образцу. Программа должна считывать в строковую переменную значение и писать соответствующее приветствие.

    Пример:

    Your name: Harry
    Hello, Harry!
    
  4. Даны два целых числа: a и b. Найти их среднее арифметическое по формуле:

    \[\frac{a + b}{2}\]
  5. Электронные часы показывают время в формате часы(h):минуты(m):секунды(s), найти количество секунд прошедшее с начала суток.

Дополнительные задачи

  1. Напишите программу, которая по данному числу n от 1 до 9 выводит на экран n пингвинов. Изображение одного пингвина имеет размер 5×9 символов, между двумя соседними пингвинами также имеется пустой (из пробелов) столбец. Для упрощения рисования скопируйте пингвина из примера в среду разработки.

    Пример:

    Penguins: 3
    
       _~_       _~_       _~_
      (o o)     (o o)     (o o)
     /  V  \   /  V  \   /  V  \
    /(  _  )\ /(  _  )\ /(  _  )\
      ^^ ^^     ^^ ^^     ^^ ^^
    
  2. Неспокойно сейчас на стапелях шестого дока межгалактического порта планеты Торна. Всего через месяц закончится реконструкция малого броненесущего корвета «Эния». И снова этому боевому кораблю и его доблестной команде предстоят тяжелые бои за контроль над плутониевыми рудниками Сибелиуса. Работа не прекращается ни на секунду, лазерные сварочные аппараты работают круглые сутки. От непрерывной работы плавятся шарниры роботов-ремонтников. Но задержаться нельзя ни на секунду. И вот в этой суматохе обнаруживается, что термозащитные панели корвета вновь требуют срочной обработки сульфидом тория. Известно, что на обработку одного квадратного метра панели требуется 1 нанограмм сульфида. Всего необходимо обработать N прямоугольных панелей размером A на B метров. Вам необходимо как можно скорее подсчитать, сколько всего сульфида необходимо на обработку всех панелей «Энии». И не забудьте, что панели требуют обработки с обеих сторон.

  3. Решите задачу 2 для целых чисел без использования дополнительной переменной.

Домашнее задание

  1. Установить Python на домашний ПК. Официальный сайт: https://www.python.org/

  2. Программа считывает 2 целых числа. Вычислите их сумму, разность, произведение, частное.

  3. Дана длина ребра куба a. Найти объем куба V и площадь его поверхности \(S = 6 \cdot a^2\).

Целочисленная арифметика

Основные определения

Арифметический оператор (operator)

Специальный символ, выполняющий арифметические вычисления. В выражении a * b символ * — оператор умножения, a и b — его операнды.

Оператор, принимающий два операнда, называется бинарным. Унарный оператор принимает один операнд. Пример унарного оператора: -1.

Выражение (expression)

Последовательность операторов и операндов, результат вычисления которой сводится к единственному значению. Простейшие выражения состоят из одного значения и не содержат операторов: 42, "Hello, World!". Пример более сложного выражения: 2 ** 32 - 1.

Приоритет операций

Свойство оператора, влияющее на очередность его выполнения в выражении с несколькими различными операторами при отсутствии явного (с помощью скобок) указания на порядок их вычисления.

Например, результат выражения 2 + 2 * 2 — 6, поскольку приоритет операции умножения выше, чем приоритет операции сложения. Изменить порядок вычислений в выражении можно с помощью скобок:

>>> (2 + 2) * 2
8
Ассоциативность

последовательность выполнения операций (или направление вычисления), реализуемая когда операции имеют одинаковый приоритет и отсутствует явное (с помощью скобок) указание на очерёдность их выполнения.

Различают правую (справа налево) и левую (слева направо) ассоциативность. Пример оператора с левой ассоциативностью — оператор деления /. Так, выражение 8 // 4 // 2 эквивалентно (8 // 4) // 2 и его результат равен 1.

Пример оператора с правой ассоциативностью — оператор возведения в степень:

>>> 2 ** 2 ** 3
256
>>> 2 ** (2 ** 3)
256
>>> (2 ** 2) ** 3
64

Арифметические операторы

В таблице приведены некоторые арифметические операторы языка Python в порядке уменьшения приоритета (операторы с наибольшим приоритетом расположены выше).

Операторы

Описание

Ассоциативность

(выражения...)

Круглые скобки

**

Возведение в степень

Справа налево

+x, -x

Унарные плюс и минус

*, /, //, %

Умножение, деление, целочисленное деление,
взятие остатка от деления

Слева направо

+, -

Сложение и вычитание

Целочисленное деление и взятие остатка от деления

Рассмотрим выражение \(7 / 2\). Частное можно записать в виде десятичной дроби: \(3.5\). Однако в ряде задач нам нужны отдельно целая часть и остаток от деления. Очевино, целая часть результата равна \(3\). Тогда для вычисления остатка от \(7\) нужно отнять произведение целой части на делимое, т.е. остаток равен \(7 - 3 \cdot 2\).

Такие операции поддерживаются в Python напрямую. Так, для целочисленного деления используется оператор //, а для получения остатка от деления оператор %:

>>> 7 // 2
3

>>> 7 % 2  # то же, что и 7 - (7 // 2 * 2)
1

Эти операции полезны при вычислениях с отдельными разрядами чисел.

Пусть дано число \(8192\), и нам необходимо получить его третий разряд, т.е. единицу. \(8192 // 10^2 \% 10 = 8192 // 100 \% 10 = 81 \% 10 = 1\).

Функции перевода чисел в различные системы счисления

bin(x)
oct(x)
hex(x)

Функции принимают целое число и возвращают его строковое представление в двоичной, восьмеричной и шестнадцатеричной системах счисления соответственно.

Пример:

>>> bin(255), oct(255), hex(255)
('0b11111111', '0o377', '0xff')

>>> bin(29), oct(29), hex(29)
('0b11101', '0o35', '0x1d')
int(x, base)

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

>>> int('101')
101
>>> int('101', 2)
5

Задачи

  1. Дано целое десятичное число. Выведите его последнюю цифру.

  2. Дано целое десятичное число. Найдите число десятков в его десятичной записи.

  3. Дано трехзначное число. Найдите сумму его цифр.

  4. Пирожок в столовой стоит \(a\) рублей и \(b\) копеек. Определите, сколько рублей и копеек нужно заплатить за \(n\) пирожков.

    Приложение запрашивает у пользователя стоимость одного пирожка и количество пирожков. Пример:

    Введите стоимость одного пирожка.
    Рубли: 2
    Копейки: 60
    Количество пирожков: 3
    

    Приложение должно вычислить стоимость запрошенного количества пирожков. Пример вывода:

    Сумма заказа: 7 рублей 80 копеек
    
  5. Дано число \(n\). С начала суток прошло n минут. Определите, сколько часов и минут будут показывать электронные часы в этот момент. Программа должна вывести два числа: количество часов (от 0 до 23) и количество минут (от 0 до 59). Учтите, что число \(n\) может быть больше, чем количество минут в сутках.

Дополнительные задачи

  1. В школе решили набрать три новых математических класса. Так как занятия по математике у них проходят в одно и то же время, было решено выделить кабинет для каждого класса и купить в них новые парты. За каждой партой может сидеть не больше двух учеников. Известно количество учащихся в каждом из трёх классов. Сколько всего нужно закупить парт чтобы их хватило на всех учеников? Программа получает на вход три целых десятичных числа: количество учащихся в каждом из трех классов.

  2. Обувная фабрика собирается начать выпуск элитной модели ботинок. Дырочки для шнуровки будут расположены в два ряда, расстояние между рядами равно \(a\), а расстояние между дырочками в ряду \(b\). Количество дырочек в каждом ряду равно \(N\). Шнуровка должна происходить элитным способом «наверх, по горизонтали в другой ряд, наверх, по горизонтали и т.д.» (см. рисунок). Кроме того, чтобы шнурки можно было завязать элитным бантиком, длина свободного конца шнурка должна быть \(l\). Какова должна быть длина шнурка для этих ботинок?

    Программа получает на вход четыре натуральных числа \(a\), \(b\), \(l\) и \(N\) и должна вывести одно число — искомую длину шнурка.

    _images/shoelaces.gif

3. Занятия в школе начинаются в 9:00. Продолжительность урока — 45 минут, перемены - 10 минут. На вход принимается номер урока, а выводится время, в которое он заканчивается (часы и минуты отдельно). Пример вывода:

Урок №2 заканчивается в 10 часов 40 минут

4. Доработайте код задачи № 3 таким образом, чтобы он запрашивал время начала занятий (минуты и часы отдельно) и номер урока, а далее также рассчитывал время окончания уроков.

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

Введите число: 01100010
Укажите систему счисления: 2
Число в десятичной системе счисления: 98
Число в двоичной системе счисления: 0b1100010
Число в восьмеричной системе счисления: 0o142
Число в шестнадцатеричной системе счисления: 0x62

Домашнее задание

  1. Дано трехзначное число. Найти произведение его цифр.

  2. Даны значения двух моментов времени, принадлежащих одним и тем же суткам: часы, минуты и секунды для каждого из моментов времени. Известно, что второй момент времени наступил не раньше первого. Определите, сколько секунд прошло между двумя моментами времени.

  3. Дано целое число \(n\). Выведите следующее за ним четное число.

Числа с плавающей точкой

Теория

Десятичные дроби в Python хранятся в формате с плавающей точкой и представлены типом float. Они могут быть записаны несколькими способами:

>>> 1.
1.0

>>> .1
0.1

>>> 4.2
4.2

>>> 4.2e3  # то же, что и 4.2 * 10 ** 3 == 4.2 * 1000
4200.0

>>> 4.2e-3  # то же, что и 4.2 * 10 ** (-3) == 4.2 * 0.001
0.0042
float(x)

Конструкция float(x) принимает строку или целое число и возвращает число с плавающей точкой, т.е. объект типа float. Примеры:

>>> float("1.2")
1.2

>>> float(42)
42.0

>>> float("42e3")
42000.0

Для вывода чисел с плавающей точкой, как и для вывода других объектов, может быть использована функция print:

pi = 3.1415
print(pi)
print(f"pi = {pi}")

Также существует способ указать количество выводимых знаков после запятой:

pi = 3.1415
print(f"pi = {pi:.3f}")
print(f"pi = {pi:.4f}")

При преобразовании чисел с плавающей точкой в целые дробная часть отбрасывается, округления по арифметическим правилам не выполняется:

>>> int(42.9)
42

Для решения вычислительных задач может быть полезен модуль math из стандартной библиотеки языка Python. Для его использования нужно написать строку import math. Для решения задач нам понадобятся число \(\pi\) и функция извлечения квадратного корня. Примеры их использования:

import math


print(f"pi = {math.pi}")

r = math.sqrt(4)
print(f"square root of 4 = {r}")

Задачи

  1. Дан диаметр окружности \(d\). Найти ее длину по формуле \(length = \pi \cdot d\).

  2. Дано значение температуры \(t\_f\) в градусах Фаренгейта. Определить значение этой же температуры в градусах Цельсия. Температура по Цельсию \(t\_c\) и температура по Фаренгейту \(t\_f\) связаны следующим соотношением:

    \[t\_c = (t\_f - 32) \cdot \frac{5}{9}\]
  3. Найти значение функции \(y = 3x^6 - 6x^2 - 7\) при заданном значении \(x\).

  4. Даны два неотрицательных числа \(a\) и \(b\). Найти их среднее геометрическое по формуле \(\sqrt{a \cdot b}\).

  5. Даны катеты прямоугольного треугольника \(a\) и \(b\). Найти его гипотенузу \(c\) и периметр \(p\):

    \[ \begin{align}\begin{aligned}c = \sqrt{a^2 + b^2}\\p = a + b + c\end{aligned}\end{align} \]
  6. Найти значение функции \(y = 4(x - 3) ^ 6 - 7(x-3) ^ 3 + 2\) при заданном значении \(x\).

  7. Дан радиус круга, найти его площадь по формуле \(s = \pi \cdot r ^ 2\).

  8. Дано значение температуры в градусах Цельсия. Вычислить значение этой же температуры в градусах Фаренгейта. Формулу вывести самостоятельно.

  9. Дан объем данных в мегабайтах. Перевести его в гигабайты и килобайты. Результат вывести с точностю до двух знаков после запятой.

Основы работы со строками

Строка

Неизменяемая последовательность символов.

Строковые литералы

Строковый литерал может быть записан в одинарных или двойных кавычнах:

>>> "Hello"
'Hello'

>>> 'World'
'World'

Разницы между этими двумя формами записи нет. Записывать строки в двойных кавычках удобно в случаях, когда в тексте содержится апостроф:

>>> "What's your name?"
"What's your name?"

Запись в апострофах удобна, если в тексте есть кавычки:

>>> 'He said: "Bond, James Bond."'
'He said: "Bond, James Bond."'

Иначе интерпретатор будет считать ближайшие кавычку или апостроф закрывающими, и их нужно экранировать:

>>> 'What\'s your name?'
"What's your name?"

>>> "He said: \"Bond, James Bond.\""
'He said: "Bond, James Bond."'

Внутри строки могут быть управляющие последовательности. Некоторые из них:

Последовательность

Описание

\\

Обратный слеш (\)

\'

Апостроф

\"

Кавычка

\t

Символ табуляции

\n

Перевод строки

Примеры:

>>> print("Hello\nWorld")
Hello
World

>>> print("1\t2\n30\t4")
1       2
30      4

В некоторых случаях экранирование обратного слеша может быть неудобно. Можно воспользоваться литералом сырых строк:

>>> print(r"Hello\nWorld")
Hello\nWorld

Операции со строками

len(s)

Получение длины строки:

>>> len("Hello")
5
s1 + s2

Конкатенация строк:

>>> "Hello " + "World"
'Hello World'
s * n

Повторение строки n раз:

>>> "python " * 3
'python python python '
s[i]

Обращение к символу i строки s. Индексация начинается с нуля. Индексы могут быть отрицательными, тогда отсчет ведется с конца строки:

>>> s = 'abcdef'
>>> s[0]
'a'
>>> s[5]
'f'
>>> s[-1]
'f'
>>> s[-2]
'e'
s[begin:end:step]

Получение среза строки от позиции begin до позиции end с шагом step. Любой параметр может быть пропущен:

>>> s = "abcdef"
>>> s[1:]
'bcdef'
>>> s[:-1]
'abcde'
>>> s[1:-1]
'bcde'
>>> s[1::2]
'bdf'
>>> s[::2]
'ace'
>>> s[::-2]
'fdb'

Задачи

  1. Пользователь вводит слово. Подсчитать количество символов в нем.

  2. Пользователь вводит слово. Вывести его первую и последнюю буквы.

  3. Пользователь вводит число. Вывести соответствующее количество кроликов. Пример:

    Rabbits: 1
     (\_/)
    =(^.^)=
    (“)_(“)
    
    Rabbits: 3
     (\_/)    (\_/)    (\_/)
    =(^.^)=  =(^.^)=  =(^.^)=
    (“)_(“)  (“)_(“)  (“)_(“)
    
  4. Дана строка, содержащая путь к файлу:

    C:\Python3\python.exe
    

    С помощью срезов вывести отдельно имя файла, его расширение, имя каталога и полный путь к каталогу. Пример вывода:

    Имя файла: python.exe
    Расширение: exe
    Имя каталога: Python3
    Полный путь к каталогу: C:\Python3\
    
  5. Дана строка 12'345'678. Используя срезы и преобразование типов получить из нее число.

  6. Пользователь вводит названия трех глав книги и номера их страниц. Вывести получившиееся содержание так, чтобы названия глав были выровнены по левому краю, а номера страниц — по правому. Ширину страницы принять за 50 символов.

    Входные данные:

    Chapter 1: Мальчик, который выжил
    Page: 5
    Chapter 2: Косой переулок
    Page: 40
    Chapter 3: Человек с двумя лицами
    Page: 500
    

    Вывод:

    Содержание
    Мальчик, который выжил                 5
    Косой переулок                        40
    Человек с двумя лицами               500
    

Дополнительные задачи

Разработать приложение, которое запрашивает у пользователя стоимость заказа из трех пунктов и выводит чек таким образом, что все стоимости выводятся в крайнем правом столбце. Ширину чека принять за 30 символов. Пример:

Салат: 60
Первое: 45
Второе: 120

Ваш счет
Салат:                    60.0
Первое:                   45.0
Второе:                  120.0
------------------------------
Итого:                   225.0

Домашнее задание

На вход программе подается строка. Необходимо вывести:

  1. Сначала выведите третий символ этой строки.

  2. Во второй строке выведите предпоследний символ этой строки.

  3. третьей строке выведите первые пять символов этой строки.

  4. В четвертой строке выведите всю строку, кроме последних двух символов.

  5. В пятой строке выведите все символы с четными индексами (считая, что индексация начинается с 0, поэтому символы выводятся начиная с первого).

  6. В шестой строке выведите все символы с нечетными индексами, то есть начиная со второго символа строки.

  7. В седьмой строке выведите все символы в обратном порядке.

  8. В восьмой строке выведите все символы строки через один в обратном порядке, начиная с последнего.

  9. В девятой строке выведите длину данной строки.

Пример:

Input: Abrakadabra
Output:
r
r
Abrak
Abrakadab
Arkdba
baaar
arbadakarbA
abdkrA
11

Методы строк

О методах

До сих пор мы использовали функции, которые были «сами по себе»: input, print. В языке Python существуют специальные функции, привязанные к объектам. Они называются методы. Сравните вызов обычной свободной функции len() и вызов метода строки upper():

>>> s = "hello"
>>> len(s)
5
>>> s.upper()
'HELLO'

Здесь функция len в качестве своего единственного аргумента принимает строку s и возвращает количество символов в ней. Метод upper() связан с типом str и вызывается у объекта s с помощью точки.

Аналогично методы можно вызывать и у литералов:

>>> 'world'.upper()
'WORLD'
s.lower()
s.upper()
s.title()

Методы приводят строку к нижнему, верхнему и title регистру соответственно:

>>> 'world'.upper()
'WORLD'
>>> 'HELLO'.lower()
'hello'
>>> 'hello'.upper()
'HELLO'
>>> 'hello'.title()
'Hello'
s.count(sub)

Возвращает количество вхождений подстроки sub в строку s.

s.find(sub)

Возвращает минимальный индекс вхождения подстроки sub в строку s:

>>> 'otto'.find('t')
1
s.rfind(sub)

Возвращает максимальный индекс вхождения подстроки sub в строку s:

>>> 'otto'.rfind('t')
2
ljust(width)

Возвращает строку, выровненную по левой границе поля ширины width. Строка дополняется пробелами справа:

>>> 'hello'.ljust(10)
'hello     '
rjust(width)

Возвращает строку, выровненную по правой границе поля ширины width. Строка дополняется пробелами слева:

>>> 'hello'.rjust(10)
'     hello'
replace(old, new)

Возвращает строку, в которой все вхождения подстроки old заменены на подстроку new.

Задачи

  1. Пользователь вводит фамилию, имя и отчество. Приложение должно вывести фамилию и инициалы. Пример:

    Фамилия: Ершов
    Имя: Андрей
    Отчество: Петрович
    
    Ершов А. П.
    
  2. Доработать приложение из предыдущей задачи так, чтобы программа исправляла регистр символов. Пример:

    Фамилия: ерШоВ
    Имя: андрей
    Отчество: петрович
    
    Ершов А. П.
    
  3. Пользователь вводит слово. Подсчитать количество символов ‘a’ в нем. Пример:

    word: abracadabra
    
    5
    
  4. Пользователь вводит строку. Нужно удалить из нее первое слово. Разделителем слов считать пробел. Пример:

    > Hello, World!
    World
    
  5. Пользователь вводит строку. Нужно удалить из нее последнее слово.

  6. Пользователь вводит строку, содержащую два слова. Приложение выводит их в обратном порядке. Пример:

    Harry Potter
    Potter Harry
    
  7. Пользователь вводит строку и два слова. Приложение заменяет все вхождения первого слова на второе. Пример:

    > To be or not to be.
    Find: be
    Replace: eat
    
    To eat or not to eat.
    
  8. Приложение принимает на вход строку и заменяет все вхождения буквы «ё» на букву «е».

  9. Написать приложение, выполняющее транслитерацию введенного слова. Пример:

    > Иван
    
    Ivan
    
  10. Пользователь вводит адрес электронной почты, нужно вывести отдельными строками почтовый логин и домен:

    > vasya@mail.ru
    
    Login: vasya
    Domain: mail.ru
    

Ветвления

Логический тип данных

В языке Python логический тип данных представлен типом bool (бул, булев тип, булевый тип).

Объекты типа bool могут принимать одно из двух значений: True (истина) или False (ложь).

Операции отношения

Существует ряд операций, результатом вычисления которых являются объекты типа bool. Рассмотрим некоторые из них:

  1. Операции отношения: <, <=, >, >=.

  2. Проверка объектов на равенство. Операция == возвращает True, если ее операнды имеют одинаковые значения. Обратная ей операция — !=:

    >>> a = 4
    >>> b = 2
    
    >>> a == b
    False
    
    >>> a != b
    True
    
  3. Логические операции: and, or, not. Работа этих операций описана в таблицах истинности ниже.

Таблицы истинности логических операций

Логическое «И» (конъюнкция, логическое умножение)

A

B

A and B

0

0

0

0

1

0

1

0

0

1

1

1

Логическое «ИЛИ» (дизъюнкция, логическое сложение)

A

B

A or B

0

0

0

0

1

1

1

0

1

1

1

1

Логическое «НЕ» (инверсия, отрицание)

A

not A

0

1

1

0

Условный оператор

Чаще всего логические выражения и операции отношения используются в условных конструкциях. В общем виде конструкция выглядит так:

if условие1:
    # Блок кода, выполняющийся в случае,
    # если <условие> принимает значение True
elif условие2:
    # ...
    # ...
else:
    # Блок кода, выполняющийся в случае,
    # если все предыдущие условия принимают значение False
    # Этот блок должен идти последним.

Блоки elif и else необязательны.

Важно: блоки кода в Python оформляются с отступами в 4 пробела (вставить такой отступ можно нажатием клавиши <Tab>).

К условию относится только код, написанный с отступом. Сравните две записи:

# 1
if False:
    print('1')
print('2')

# 2
if False:
    print('1')
    print('2')

Задачи

  1. Пользователь вводит число. Приложение сообщает, является это число положительным, отрицательным или нулем.

  2. Пользователь вводит номер месяца, приложение сообщает, какое это время года. Весна (3,4,5), лето (6,7,8), осень (9,10,11) зима (12,1,2)).

    Пример:

    Номер месяца: 6
    Лето
    
    Номер месяца: 12
    Зима
    
    Номер месяца: 13
    Такого месяца нет
    
  3. Пользователь вводит три целых числа. Найти количество положительных и количество отрицательных чисел среди них.

  4. Пользователь вводит три числа. Определить минимальное и максимальное из них.

  5. Пользователь вводит год. Приложение сообщает, является ли этот год високосным. Год является високосным, если он делится без остатка на 4 и вместе с этим либо делится без остатка на 400, либо не делится без остатка на 100.

  6. Пользователь вводит часы, минуты и секунды в 24-часовом формате. Приложение проверяет корректность введенных чисел. Для каждого несоответствия вывести сообщение с корректными диапазонами. Пример:

    Часы: 2
    Минуты: 25
    Секунды: 13
    
    Все верно. Время 2:25:13
    
    
    Часы: 25
    Минуты: 70
    Секунды: 59
    
    Ошибка!
    Часы должны быть в диапазоне [0:23]
    Минуты должны быть в диапазоне [0:59]
    
  7. Пользователь вводит число, операцию и еще одно число. Приложение выполняет вычисления. Реализовать поддержку операций +, -, *, /. Пример:

    Число а: 17
    Операция: +
    Число b: 10
    
    Результат: 17 + 10 = 27
    
  8. Пользователь вводит шестизначный номер билета. Приложение определяет, является ли он счастливым. Билет счастливый, если сумма первых его трех цифр равна сумме последних трех.

Ветвления 2

str.isalpha()

Возвращает True, если строка str состоит из букв.

str.isnumeric()

Возвращает True, если строка str состоит из цифр.

str.isalnum()

Возвращает True, если строка str состоит из букв и/или цифр.

str.islower()
str.isupper()
str.istitle()

Методы возвращают True, если строка str записана в нижнем, верхнем или title регистре соответственно.

Задачи

  1. Пользователь вводит имя. Приложение сообщает, является ли имя корректным. Имя считается корректным, если записано в title case и состоит только из букв.

  2. Пользователь вводит двузначное число. Определить:

    1. Какой из его разрядов больше: старший или младший.

    2. Одинаковы ли разряды.

  3. По длинам трех отрезков, введенных пользователем, определить возможность существования треугольника, составленного из этих отрезков. Если такой треугольник существует, то определить, является ли он разносторонним, равнобедренным или равносторонним.

  4. Пользователь вводит слово. Проверить, является ли оно палиндромом.

  5. Доработать предыдущую задачу так, чтобы приложение игнорировало регистр символов.

  6. Пользователь вводит число. Приложение сообщает количество хомячков в с учетом падежа. Пример:

    Число: 21
    
    21 хомячок
    
    
    Число: 42
    
    42 хомячка
    
    
    Число: 12
    
    12 хомячков
    
  7. Пользователь вводит пароль. Приложение сообщает, надежен ли он. Пароль считается надежным, если:

    1. Его длина более 6 символов

    2. Есть символы как в верхнем, так и в нижнем регистре

    3. Есть цифры или специальные символы (пока считаем, что достаточно проверить наличие любых символов помимо букв)

  8. Приложение запрашивает имя пользователя. Если пользователь вводит «admin», то дополнительно запрашивает пароль. Если пароль равен «123», то приветствует пользователя. Если пользователь представляется другим именем, то приложение приветствует его без запроса пароля.

  9. Пользователь вводит два числа: день и месяц невисокосного кода. Вывести дату следующего дня.

Циклы

Цикл while

Цикл while позволяет многократно выполнять блок команд до тех пор, пока выполняется некоторое условие. Пример:

n = 5

while n > 0:
    print(f'n = {n}')
    n -= 1

Вывод:

n = 5
n = 4
n = 3
n = 2
n = 1

Цикл for

Цикл for..in осуществляет итерацию по последовательности объектов, т.е. проходит через каждый элемент в последовательности. Мы узнаем больше о последовательностях на следующих уроках, а пока просто запомните, что последовательность – это упорядоченный набор элементов.

Пример:

for i in range(1, 6):
    print(f'i = {i}')

Вывод:

i = 1
i = 2
i = 3
i = 4
i = 5

В этом примере функция range возвращает объект последовательнсоти. Обратите внимание, что правая граница не включается.

Есть несколько способов создания последовательности с помощью функции range.

range(stop)
range(start, stop)
range(start, stop, step)

Возвращает последовательность от start до stop (не включительно) с шагом step.

Оператор break

Оператор break служит для прерывания цикла, т.е. остановки выполнения команд даже если условие выполнения цикла ещё не приняло значения False или последовательность элементов не закончилась.

Пример:

while True:
    command = input('> ')
    if command == 'exit':
        break

Оператор continue

Оператор continue используется, чтобы пропустить все оставшиеся команды в текущем блоке цикла и продолжить со следующей итерации цикла:

Пример:

for i in range(5):
    if i == 2 or i == 3:
        continue
    print(i)

Задачи

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

  1. [for] Пользователь вводит числа a и b. Вывести все целые числа, расположенные между ними.

  2. [for] Доработать предыдущую задачу так, чтобы выводились только числа, делящиеся на 5 без остатка.

  3. [for] Пользователь вводит число. Вывести таблицу умножения на это число

  4. [for] Известны оценки абитуриента на четырех экзаменах. Определить сумму набранных им баллов. Оценки вводятся в цикле.

  5. [while] В бесконечном цикле приложение запрашивает у пользователя числа. Ввод завершается, как только пользователь вводит слово ‘end’. После завершения ввода приложение выводит сумму чисел.

  6. [while] Дано натуральное число. Определить сумму цифр в нем.

  7. Пользователь вводит число n и цифру a. Определить, сколько раз цифра встречается в числе. (не использовать метод count)

Циклы 2

Задачи

  1. FizzBuzz — классическая задача для собеседований. Напишите приложение, которое проходит по целым числам от 1 до 50. Если число делится без остатка на 3, то вместо этого числа выведите «Fizz». Если число делится без остатка на 5, выведите «Buzz». Если число делится без остатка и на 3, и на 5, то выведите «FizzBuzz».

  2. Пользователь вводит число. Вывести рамку заданной высоты и ширины. Пример:

    side: 5
    
    #####
    #   #
    #   #
    #   #
    #####
    
  3. Пользователь вводит количество ступенек, приложение выводит лестницу:

    Steps: 5
    
         #
        ##
       ###
      ####
     #####
    
  4. Для настольной игры используются карточки с номерами от 1 до N. Одна карточка потерялась. Найдите ее, зная номера оставшихся карточек.

    Дано число N, далее N-1 номер оставшихся карточек (различные числа от 1 до N). Программа должна вывести номер потерянной карточки.

    Пример 1.

    Ввод:

    6
    1
    2
    3
    5
    6
    

    Вывод:

    4
    

    Пример 2.

    Ввод:

    6
    6
    1
    2
    4
    5
    

    Вывод:

    3
    
  5. Дана последовательность натуральных чисел, завершающаяся числом 0. Определите, какое наибольшее число подряд идущих элементов этой последовательности равны друг другу.

    Пример.

    Ввод:

    1
    2
    2
    0
    

    Вывод:

    2
    
  6. Вывести таблицу умножения. Для решения задачи вам понадобится вспомнить форматированный вывод. Для каждой колонки оптимально использовать ширину 3 символа. Для вывода нескольких чисел в одну строку без переносов можно использовать либо конкатенацию строк, либо указать функции print пустой разделитель: print(42, end='').

    Вывод:

        2  3  4  5  6  7  8  9
     -------------------------
    2|  4  6  8 10 12 14 16 18
    3|  6  9 12 15 18 21 24 27
    4|  8 12 16 20 24 28 32 36
    5| 10 15 20 25 30 35 40 45
    6| 12 18 24 30 36 42 48 54
    7| 14 21 28 35 42 49 56 63
    8| 16 24 32 40 48 56 64 72
    9| 18 27 36 45 54 63 72 81
    

Основы работы со списками и кортежами

Основные определения

Список

Список — упорядоченная изменяемая последовательность объектов произвольного типа. В языке Python списки представлены типом list.

Кортеж

Кортеж — неизменяемый аналог списков, которому соответствует тип данных tuple.

Изменяемая последовательность

Изменяемая последовательность — последвательность, в которой после ее создания возможно изменение количества элементов или присваивание им объектов.

Создание списков и кортежей

Создание списка:

>>> s = []
>>> type(s)
<class 'list'>

>>> s = [1, 2, 3]
>>> type(s)
<class 'list'>

>>> s = list('iterable_obj')
>>> type(s)
<class 'list'>
>>> s
['i', 't', 'e', 'r', 'a', 'b', 'l', 'e', '_', 'o', 'b', 'j']

Создание кортежа:

>>> s = ()
>>> type(s)
<class 'tuple'>

>>> s = 1,
>>> type(s)
<class 'tuple'>

>>> s = tuple('iterable_obj')
>>> type(s)
<class 'tuple'>
>>> s
('i', 't', 'e', 'r', 'a', 'b', 'l', 'e', '_', 'o', 'b', 'j')

Используя конструкторы list() и tuple(), можно выполнять преобразование последовательностей в список либо кортеж.

Операции со списками и кортежами

Списки и кортежи поддерживают общий для последовательностей набор операций. В примерах будет использован список:

>>> lst = [1, 2, 3]
x in s

Проверка на принадлежность элемента x последовательности s:

>>> 3 in lst
True
>>> 4 in lst
False
min(s)

Наименьший элемент последовательности:

>>> min(lst)
1
max(s)

Наибольший элемент последовательности:

>>> max(lst)
3

Методы списков и кортежей

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

s.append(x)

Вставка элемента в конец списка:

>>> x = [1, 2, 3]
>>> x.append(5)
>>> x
[1, 2, 3, 5]
s.extend(L)

Добавление элементов списка L в конец списка:

>>> x = [1, 2, 3]
>>> x.extend([4, 5, 6])
>>> x
[1, 2, 3, 4, 5, 6]
s.insert(i, x)

Вставка элемента x по индексу i:

>>> x = [1, 2, 3]
>>> x.insert(1, 5)
>>> x
[1, 5, 2, 3]
s.remove(x)

Удаление первого вхождения x из списка:

>>> x = [1, 2, 3, 3, 2, 1]
>>> x.remove(2)
>>> x
[1, 3, 3, 2, 1]
s.pop(x)

Извлечение элемента из списка:

>>> x = [1, 2, 3, 3, 2, 1]
>>> x.pop(1)
2
>>> x
[1, 3, 3, 2, 1]
>>> x.pop()
1
>>> x
[1, 3, 3, 2]
s.clear()

Удаление всех элементов из списка:

>>> x = [1, 2, 3]
>>> x.clear()
>>> x
[]
s.sort()

Сортировка списка:

>>> x = [1, 2, 3, 3, 2, 1]
>>> x.sort()
>>> x
[1, 1, 2, 2, 3, 3]
s.reverse()

Изменение порядка элементов на обратный:

>>> x = [1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1]
s.index(x)

Поиск индекса первого вхождения элемента:

>>> x = [1, 2, 3, 3, 2, 1]
>>> x.index(2)
1

Задачи

  1. Пользователь вводит числа a и b. Создать список, содержащий квадраты целых чисел расположенных между ними.

  2. Пользователь вводит числа до тех пор, пока не введет слово end. Поместите введенные числа в список. Выведите на экран только нечетные элементы списка.

  3. Пользователь вводит числа до тех пор, пока не введет слово ‘end’. Поместите введенные числа в список. Подсчитайте количество четных и нечетных элементов в списке.

  4. Дан список чисел. Выведите все элементы списка, которые больше предыдущего элемента.

  5. Дан список чисел. Поменяйте местами минимальный и максимальный элемент этого списка.

  6. Дан список чисел. Определите, сколько в нем различных элементов.

  7. Петя перешёл в другую школу. На уроке физкультуры ему понадобилось определить своё место в строю. Помогите ему это сделать. Программа получает на вход последовательность чисел, означающих рост каждого человека в строю. После этого вводится число X – рост Пети. Все числа во входных данных натуральные и не превышают 200. Выведите номер, под которым Петя должен встать в строй. Если в строю есть люди с одинаковым ростом, таким же, как у Пети, то он должен встать после них.

  8. Дан список чисел. Циклически сдвиньте элементы списка вправо (A[0] переходит на место A[1], A[1] на место A[2], …, последний элемент переходит на место A[0]).

Вложенные списки. Модуль random

Модуль random предоставляет функции для работы с псевдослучайными величинами. Для решения задач этого занятия понадобятся следующие функции.

random.randint(a, b)

Возвращает псевдослучайное число на отрезке [a, b].

random.choice(seq)

Возвращает случайный элемент из последовательности seq. Пример:

>>> import random
>>> t = (1, 2, 3)
>>> random.choice(t)
2
>>> random.choice(t)
1
random.shuffle(lst)

Перемешивает элементы в списке lst:

>>> lst = list(range(10))
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> random.shuffle(lst)
>>> lst
[0, 9, 3, 2, 1, 5, 7, 6, 4, 8]

Задачи

  1. Реализовать игру «Города».

    Шаг 1. Версия для двух игроков за одним компьютером. Названные города не должны повторяться.

    Шаг 2. Добавить проверку на существование города.

    Шаг 3. Реализовать режим игры против компьютера.

    Модули с подготовленными списками городов:

  2. Реализовать игру «Анаграммы». Приложение выводит слово, буквы в котором перемешаны. Игрок должен назвать исходное слово.

  3. Пользователь вводит три числа: n, min_value, max_value. Приложение создает список из n элементов и заполняет его случайными числами из [min_value, max_value].

  4. По аналогии с задачей 1 создать матрицу n на m и заполнить ее случайными числами из [min_value, max_value).

  5. Цвета кодируются тройкой (red, green, blue). Каждый компонент может принимать значения от 0 до 255. Напишите приложение, генерирующее случайный цвет. Для удобства его значение можно вывести в шестнадцатеричном формате (например, 345EBF). Для просмотра полученного цвета можно использовать сервис https://colorscheme.ru/.

  6. Пользователь вводит число n. Приложение создает и выводит матрицу, заполненную «змейкой». Пример:

     n: 5
    
     1    2    3    4    5
    10    9    8    7    6
    11   12   13   14   15
    20   19   18   17   16
    21   22   23   24   25
    
  7. Реализовать приложение-лотерею. Пусть лотерейный билет хранится как список списков:

    ticket = [
        [ 1,  2,  3,  4,  5],
        [ 6,  7,  8,  9, 10],
        [11, 12, 13, 14, 15],
        [16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25],
    ]
    

    Пользователь должен выбрать пять чисел: по одному числу из каждой строки. Числа могут быть выбраны в любом порядке. Приложение делает аналогичный выбор случайным образом, а затем выводит статистику. Пример:

    row 0 3
    row 1 7
    row 2 14
    row 3 19
    row 4 21
    
    User Random
       3      1 -
       7      9 -
      14     13 -
      19     19 +
      21     23 -
    

Функции

Функции – это многократно используемые фрагменты программы. Они позволяют дать имя определенному блоку команд для того, чтобы выполнять этот блок по указанному имени в любом месте программы и сколь угодно много раз. Это называется вызовом функции. Мы уже использовали встроенные функции: print, input, len, range;

Пример:

def say_hello():
    print('Hello')

say_hello()  # вызов функции
say_hello()  # ещё один вызов функции

Параметры функций

Функции могут принимать параметры, т.е. некоторые значения, передаваемые функции для того, чтобы она что-либо сделала с ними.

Параметры указываются в скобках при объявлении функции и разделяются запятыми. Аналогично мы передаём значения, когда вызываем функцию. Обратите внимание на терминологию: имена, указанные в объявлении функции, называются параметрами, тогда как значения, которые вы передаёте в функцию при её вызове, – аргументами.

Пример:

def print_max(a, b):
    if a > b:
        print(a, 'максимально')
    elif a == b:
        print(a, 'равно', b)
    else:
        print(b, 'максимально')

print_max(3, 4)  # прямая передача значений

x = 5
y = 7

print_max(x, y)  # передача переменных в качестве аргументов

Локальные переменные

При объявлении переменных внутри определения функции, они никоим образом не связаны с другими переменными с таким же именем за пределами функции – т.е. имена переменных являются локальными в функции. Это называется областью видимости переменной. Область видимости всех переменных ограничена блоком, в котором они объявлены, начиная с точки объявления имени.

Пример:

x = 50

def func(x):
    print('x равен', x)
    x = 2
    print('Замена локального x на', x)

func(x)
print('x по-прежнему', x)

Значения аргументов по умолчанию

Часть параметров функций могут быть необязательными, и для них будут использоваться некоторые заданные значения по умолчанию, если пользователь не укажет собственных. Этого можно достичь с помощью значений аргументов по умолчанию. Их можно указать, добавив к имени параметра в определении функции оператор присваивания (=) с последующим значением.

Обратите внимание, что значение по умолчанию должно быть неизменным.

Пример:

def say(message, times=1):
    print(message * times)

say('Hello')
say('World', 5)

Ключевые аргументы

Если имеется некоторая функция с большим числом параметров, и при её вызове требуется указать только некоторые из них, значения этих параметров могут задаваться по их имени – это называется ключевые параметры. В этом случае для передачи аргументов функции используется имя (ключ) вместо позиции (как было до сих пор).

Пример:

def func(a, b=5, c=10):
    print('a равно', a, ', b равно', b, ', а c равно', c)

func(3, 7)
func(25, c=24)
func(c=50, a=100)

Переменное число параметров

Иногда бывает нужно определить функцию, способную принимать любое число параметров:

def mysum(*numbers):
    s = 0
    for n in numbers:
        s += n

    print(f'sum = {s}')

mysum(1)
mysum(1, 2, 3)

Оператор return

Оператор return используется для возврата из функции, т.е. для прекращения её работы и выхода из неё. При этом можно также вернуть некоторое значение из функции:

def maximum(x, y):
    if x > y:
        return x
    elif x == y:
        return 'Числа равны.'
    else:
        return y

print(maximum(2, 3))

Из функции можно вернуть только одно значение. Если все-таки необходимо вернуть несколько значений, то для этого можно использовать кортеж:

def div_mod(a, b):
    return a // b, a % b

r1 = div_mod(11, 2)  # r1 - кортеж (5, 1)
d, m = div_mod(11, 2)  # деструктурирование кортежа

Задачи

В задачах этого раздела вам даны заготовки для самопроверки. Этот код нужно скопировать и разместить после определения своей функции. Так, если вам дан код:

assert add(40, 2) == 42
assert add(0, -1) == -1

то ваш файл с исходным кодом должен выглядеть так:

def add(a, b):
    return a + b


assert add(40, 2) == 42
assert add(0, -1) == -1
  1. Прочитайте документацию на функцию print: https://docs.python.org/3/library/functions.html#print

    Расскажите о назначении каждого параметра.

  2. Реализовать функцию is_sorted. Функция принимает на вход список и возвращает True, если элементы в нем упорядочены по возрастанию.

    assert is_sorted([]) == True
    assert is_sorted([42]) == True
    assert is_sorted([3, 14, 15, 92]) == True
    assert is_sorted([1, 1, 1]) == True
    assert is_sorted([1, 1, 2, 2, 3, 3, 3]) == True
    assert is_sorted([2, 1]) == False
    assert is_sorted([1, 2, 1]) == False
    
  3. Реализовать функцию find_longest. Функция принимает на вход список строк и возвращает строку с максимальной длиной. Если таких строк несколько, то возвращает первую из них.

    assert find_longest([]) == None
    assert find_longest([""]) == ""
    assert find_longest(["42"]) == "42"
    assert find_longest(["uno", "dos", "tre"]) == "uno"
    assert find_longest(["a", "bb", "ccc"]) == "ccc"
    assert find_longest(["a", "ccc", "bb"]) == "ccc"
    
  4. Реализовать функцию min_max. Функция принимает на вход список чисел и возвращает пару: минимальное и максимальное число. Алгоритм должен выполнять не более одного прохода по списку.

    assert min_max([]) == (None, None)
    assert min_max([1]) == (1, 1)
    assert min_max([1, 1]) == (1, 1)
    assert min_max([1, 2]) == (1, 2)
    assert min_max([2, 1]) == (1, 2)
    assert min_max([14, 3, 14, 92, 15]) == (3, 92)
    
  5. Реализовать функцию zip_longest_sum. Функция принимает на вход два списка и возвращает новый список, полученный сложением соответствующих элементов входных списков.

    assert zip_sum_longest([], []) == []
    assert zip_sum_longest([1], []) == [1]
    assert zip_sum_longest([], [1]) == [1]
    assert zip_sum_longest([1], [2]) == [3]
    assert zip_sum_longest([1], [2, 1]) == [3, 1]
    assert zip_sum_longest([2, 1], [1]) == [3, 1]
    
  6. Реализовать функцию is_prime. Функция принимает на вход целое число и возвращает True, если число простое. Простым называется число, которое делится без остатка только на 1 и на себя.

    assert is_prime(5) == True
    assert is_prime(113) == True
    assert is_prime(12) == False
    
  7. Реализовать функцию join. Функция принимает разделитель и список строк, возвращает строку, в которой элементы списка чередуются с разделителем.

    assert join(' ', []) == ''
    assert join(', ', ['one']) == 'one'
    assert join(', ', ['one', 'two', 'three']) == 'one, two, three'
    

Easygui

Easygui — библиотека, предназначенная для разработки простого графического интерфейса.

Официальная документация: https://easygui.readthedocs.io/en/master/api.html

Начало работы

В первую очередь импортируем модуль easygui в файл с кодом:

import easygui

Описание функций библиотеки

easygui.buttonbox(msg='', title=' ', choices=('Button[1]', 'Button[2]'),
image=None, images=None, default_choice=None, cancel_choice=None)

Создать окно с кнопками из кортежа choices, заголовком окна title и текстом msg. Также можно задать:

  • изображение: image = ‘C:/Python/Images/123.png’

  • несколько изображений: images = [‘games/1.png’, ‘games/2.png’]

  • выделенную кнопку: default_choice = ‘Button[1]’

  • кнопку отмены: cancel_choice = ‘Button[2]’

Окно возвращает строку, равную тексту на выбранной кнопке или имени файла с изображением.

easygui.msgbox(msg='(Your message goes here)', title=' ', ok_button='OK',
image=None)

Создать текстовое сообщение с текстом msg, заголовком окна title и кнопкой ok_button. Окно возвращает текст на ``ok_butto``n.

easygui.integerbox(msg='', title=' ', default=None, lowerbound=0,
upperbound=99, image=None, root=None)

Создать окно с полем для ввода целого числа в диапазоне от lowerbound до upperbound. Дополнительно можно указать введённое по умолчанию значение default. Окно возвращает целое число, введённое в текстовое поле.

easygui.boolbox(msg='Shall I continue?', title=' ', choices=('[Y]es', '[N]o'),
image=None, default_choice='Yes', cancel_choice='No')

Создать окно с выбором “Да” и “Нет” (кортеж choices). Окно возвращает True если выбрана кнопка, отличная от cancel_choice и False, если выбрана кнопка cancel_choice.

Задание

Используя шаблон проекта, реализуйте игры «Камень, ножницы, бумага» и «Угадай число»:

import easygui


def rock_paper_scissors():
    easygui.msgbox('Здесь будет игра "Камень, ножницы, бумага"')


def guess_the_number():
    easygui.msgbox('Здесь будет игра "Угадай число"')


games = [
    'Камень, ножницы, бумага',
    'Угадай число'
]

games_entry_points = [
    rock_paper_scissors,
    guess_the_number
]

while True:
    res = easygui.buttonbox('Выбери игру!', choices=games)
    if res is None:
        break
    games_entry_points[games.index(res)]()

Шаблон проекта в архиве: games.zip

Файловый ввод-вывод

Обычно работа с файлами состоит из следующих этапов:

  1. Открыть файл. При открытии следует указать режим: чтение или запись.

  2. Выполнить чтение или запись данных.

  3. Закрыть файл.

Рассмотрим функции для выполнения этих действий.

open(file_path, mode='r')

Открыть файл file_path в режиме mode. Функция возвращает file object. Полная сигнатура функции приведена в официальной документации: open. Режим может принимать значения:

  • 'r'read, чтение

  • 'w'write, запись

f.write(text)

Записать строку text в файл.

f.close()

Закрыть файл f.

Пример работы с файлом:

# Открываем файл для записи
out_file = open('data.txt', 'w')

# Пишем в файл две строки
out_file.write('Hello\n')
out_file.write('World\n')

# Закрываем файл
out_file.close()

# Снова открываем этот же файл, но уже для чтения
in_file = open('data.txt', 'r')

# Файл — итерируемый объект. Следовательно, для
# его построчного чтения можно использовать цикл for
for line in in_file:
    print(f'Got line: {line}')

in_file.close()

Задачи

  1. Разработать приложение, которое записывает в файл все строки, введенные пользователем. Признак конца ввода — пустая строка. Пример:

    Введите имя файла: data.txt
    Начните вводить строки
    > one
    > two
    > three
    >
    
    Файл записан.
    

    После выполнения программы должен появиться файл data.txt, содержащий три строки:

    one
    two
    three
    
  2. Разработать приложение для нумерации строк в файле. Приложение принимает на вход имя файла и выводит его построчно, добавляя к каждой строке ее номер. Если использовать файл, созданный в предыдущей задаче, то результат работы программы будет выглядеть так:

    Введите имя файла: data.txt
    
    1 one
    
    2 two
    
    3 three
    

    Используйте метод строки rstrip(), чтобы избавиться от лишних переносов сток. После этого результат работы программы примет вид:

    Введите имя файла: data.txt
    1 one
    2 two
    3 three
    
  3. Разработать приложение для разделения файла на части. Приложение принимает на вход имя файла для разделения и целое число N. На выходе у приложения множество файлов, каждый из которых содержит не более, чем N строк из исходного файла.

    Пусть на вход программе подается файл data.txt, со следующим текстом:

    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
    ten
    

    Будем разделять его на несколько файлов, в каждом из которых окажется не более трех строк:

    Введите имя входного файла: data.txt
    Введите максимальное количество строк: 3
    

    После выполнения программы должны быть созданы файлы 1.txt, 2.txt и так далее. В файле 1.txt будут сроки:

    one
    two
    three
    

    В файле 2.txt:

    four
    five
    six
    

    И так далее.

  4. Разработать приложение для объединения файлов. Приложение принимает на вход имена файлов для объединения (можно использовать файлы, полученные из предыдущего задания) и имя выходного файла.

Дополнительные задачи

  1. Разработайте приложение, которое выводит N первых строк файла.

  2. Разработайте приложение, которое выводит N последних строк файла.

Шифр Цезаря

Шифр Цезаря — это вид шифра подстановки, в котором каждый символ в открытом тексте заменяется символом, находящимся на некотором постоянном числе позиций левее или правее него в алфавите. Например, в шифре со сдвигом вправо на 3, A была бы заменена на D, B станет E, и так далее.

Для кодирования одного символа используется формула:

\[encoded\_symbol = first + (symbol - first + key) \bmod (last - first + 1)\]

Здесь:

  • encoded_symbol — код зашифрованного символа

  • symbol — код исходного символа

  • key — ключ шифрования

  • first — код первого символа алфавита

  • last — код последнего символа алфавита.

Для преобразования символа в код и обратно используются функции:

ord(c)

Возвращает код символа с.

chr(i)

Возвращает символ, соответствующий коду i.

Задание

Каждая задача — отдельный этап реализации приложения для шифрования.

  1. Реализуйте функцию encode_symbol. Функция принимает символ и число, на которое его нужно сдвинуть. Функция шифрует только символы латинского алфавита, все прочие оставляет без изменений.

  2. Реализуйте функцию encode_str. Функция принимает строку и ключ шифрования и возвращает зашифрованную строку.

  3. Реализуйте функцию encode_file(input_file_path, output_file_path, key).

  4. Реализуйте для приложения графический интерфейс с помощью easygui. Для открытия шифруемого файла используйте функцию easygui.fileopenbox(msg=None, title=None). Для сохранения зашифрованного файла используйте easygui.filesavebox(msg=None, title=None). Для ввода ключа — easygui.integerbox(msg="", title=" ").

Словари

Основные определения

Словарь

Неупорядоченная коллекция объектов произвольного типа с доступом по ключу. Представлены типом dict.

Множество

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

Неупорядоченная коллекция

Коллекция, в которой элементы не индексируются и нельзя делать срезы

Создание словарей

>>> d = {}
>>> type(d)
<class 'dict'>
>>> d = {"Name": "John", "Last Name": "Connor"}
>>> d
{'Name': 'John', 'Last Name': 'Connor'}

Динамическое создание словарей:

# Словарь можно создать, передав список пар ключ-значение
pairs = [('Name', 'John'), ('Age', 19)]
d = dict(pairs)
print(d)
{'Name': 'John', 'Age': 19}


# Можно создавать такие пары с помощью функции zip
id = (1, 2, 3, 4,)
logins = ('Vasya', 'Petya', 'Lera')
# Функция zip упаковывает несколько последовательностей в кортежи
d = dict(zip(logins, id))
print(d)
{'Vasya': 1, 'Petya': 2, 'Lera': 3}

Добавление элементов осуществляется с помощью фигурных скобок:

>>> d['Age'] = 19

Получение элемента по ключу:

>>> d['Age']
19

Методы словарей

d.get(key)

Получение элемента по заданному ключу:

>>> d.get('Name')
'John'
>>> d.get('Not Presented Key')
None
d.keys()

Получение списка всех ключей

>>> d.keys()
dict_keys(['Name', 'Last Name'])
d.values()

Получение списка всех значений в словаре

>>> d.values()
dict_values(['John', 'Connor'])
d.items()

Получение списка пар ключ-значение, представленных в виде кортежей:

>>> d.items()
dict_items([('Name', 'John'), ('Last Name', 'Connor')])
d.pop(key)

Извлечение элемента из словаря:

>>> d = {'Name': 'John', 'Last Name': 'Connor'}
>>> d.pop('Name')
'John'
>>> d
{'Last Name': 'Connor'}
dict.fromkeys(seq, value)

Создаёт новый словарь, в котором ключи взяты из последовательности seq и им установлены значения по умолчанию value:

>>> lst = ['uesr1', 'user2', 'user3']
>>> user_logins_with_passwords = dict.fromkeys(lst, 123456)
>>> user_logins_with_passwords
{'uesr1': 123456, 'user2': 123456, 'user3': 123456}

Задачи

  1. Написать программу, которая на вход получает файл и выводит на экран уникальные слова. Использовать тип set.

  2. Написать программу, которая на вход получает файл и выводит на экран какое слово сколько раз встречалось. Использовать тип dict.

  3. Создайте функцию compute_bill, считающаю итоговую сумму товаров в чеке. Функция должна принимать 1 параметр - словарь, в котором указано количество едениц товара. Цены хранятся в словаре:

    prices = {
      "banana": 4,
      "apple": 2,
      "orange": 1.5,
      "pear": 3
    }
    
  4. Создайте программу, которая будет выводить все возможные комбинации при броске 2 игральных костей и сумму их значений. Пример вывода:

    2: [(1, 1)]
    3: [(1, 2), (2, 1)]
    ...
    

Основы работы с библиотекой requests

В основе ежедневной работы пользователей в сети Интернет лежит обмен данными между клиентскими приложениями (например браузер) и веб-серверами. В соответствии с прикладным протоколом HTTP, клиент отправляет запрос (request) на получение определенного ресурса к серверу и получает от него ответ (response). Ответ, помимо самого запрошенного ресурса, содержит также служебную информацию.

Библиотека requests предоставляет удобный способ отправки HTTP-запросов и обработки ответов от сервера.

Рассмотрим функцию get, которая нам потребуются для отправки простых запросов.

requests.get(url, params=None, **kwargs)

Отправить GET-запрос. Функция принимает URL-адрес запрашиваемого ресурса и возвращает объект типа Response. Также возможна передача в функцию дополнительных параметров запроса.

Пример отправки запроса на получение ресурса:

url = 'http://api.forismatic.com/api/1.0/'
payload  = {'method': 'getQuote', 'format': 'json', 'lang': 'ru'}
res = requests.get(url, params=payload))

Теперь мы можем получить все необходимые данные из Response-объекта res.

Проверяем URL ресурса:

>>> res.url
'http://api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=ru'

Проверяем код ответа HTTP:

>>> res.status_code
200

Получаем заголовки ответа:

>>> res.headers
{'Date': 'Tue, 19 Feb 2019 19:27:34 GMT', 'Content-Type': 'application/json' ... }

Получаем содержимое ответа в текстовом формате:

>>> res.text

В случае бинарного содержимого ответа воспользуемся атрибутом content:

>>> res.content

Если данные в ответе представлены в формате json их можно декодировать и получить словарь:

>>> data = res.json()
>>> data['quoteText']
'Тот, кто не смотрит вперед, оказывается позади'
>>> data['quoteAuthor']
'Герберт Уэллс '

Подробная документация к библиотеке доступна по адресу: http://docs.python-requests.org/en/master/api/

Множество интернет-сервисов предоставляют программистам API (Application programming interface) — интерфейс получения данных посредством запросов, а также документацию к нему.

Задачи

  1. Реализовать приложение для получения случайных цитат.

    Шаг 1. Изучите API сервиса forismatic.com: http://forismatic.com/en/api/

    Шаг 2. С помощью модуля easygui разработайте приложение с графическим интерфейсом для получения цитат на русском и английском языках.

  2. Реализовать приложения для загрузки картинок с котиками:

    Шаг 1. Изучите API сервиса cataas.com: https://cataas.com/#/

    Шаг 2. С помощью модуля easygui разработайте приложение для загрузки случайных картинок с котиками. Картинка содержится в ответе от сервера в бинарном виде.

  3. Реализовать приложение, которое запрашивает у пользователя дату и возвращает список праздников в эту дату:

    Шаг 1. Изучите API сервиса: https://date.nager.at/

    Шаг 2. С помощью модуля easygui разработайте приложение, которое принимает на вход дату в определённом формате, а возвращает список праздников в эту дату.

Классы

Класс — шаблон, с помощью которого удобно описывать однотипные объекты. В классе соержатся свойства, правила создания и поведение объекта.

  • Объект — экземпляр, созданный на основе шаблона.

  • Атрибут — поле, хранящее значение. Содержит свойства объекта.

  • Метод — функция, связанная с классом. Описывает поведение или действия объекта.

Пример класса - автомобили, его атрибутами будут: цвет, марка автомобиля, регистрационный номер.

Методами могут быть: ехать прямо, повернуть, остановиться.

Объектом класса “Автомобили” может быть конкретный автомобиль, например, Renault Logan белого цвета с номером М123РТ.

Для чего нужны классы?

Классы помогают кратко и понятно описывать объекты и их поведение независимо от основного кода программы.

Затем в основном коде можно просто создавать объекты на основе классов и работать с ними, уже не описывая их свойств и поведения.

Такой подход делает код более читаемым и понятным, а также помогает избежать многих ошибок и багов.

Посмотреть слайды.

Синтаксис и правила создания классов

Для создания класса используется конструкция class ClassName. Согласно договорённостям имя класса всегда пишется с большой буквы.

Каждый класс должен содержать метод __init__ - с помощью этого метода создаётся объект класса. В этом методе инициализируются атрибуты класса:

class Person:  # Объявления класса
    def __init__(self, name, age): # Метод инициализации
        self.age = age   # Установка значений атрибутов
        self.name = name

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

Название

Применение

__init__

Инициализация объекта

__str__

Преобразование к строке str(obj)

__eq__

Проверка на равенство ==

__getitem__

Оператор доступа к элементам |
some_dict[‘item’] |

Пример:

class Person:  # Объявления класса
    def __init__(self, name, age): # Метод инициализации
        self.age = age   # Установка значений атрибутов
        self.name = name

    def __str__(self):
        return f"{self.name} is {self.age} years old"


person = Person('John', 20)  # Создание экземпляра
person.name = 'James' # Установка значения атрибута

print(person)

Задачи

  1. Создать класс, описывающий человека. Должны быть поля для имени, фамилии и возраста. Создать экземпляр и вывести информацию о человеке.

  2. Доработать предыдущий класс, чтобы вся информация о человеке была доступна при вызове str над экземпляром.

  3. Добавить метод greet, вызов которого будет выводить в консоль информацию о человеке в формате "Привет! Меня зовут Петров Василий, мне 12 лет".

  4. Добавить атрибут grades, в котором будет храниться список оценок. Создать список учеников, заполняя оценки случайными числами, и вывести информацию о них в порядке убывания среднего балла. Заполнение оценок и подсчёт среднего балла вынести в отдельные методы.

  5. Создайте класс прямоугольник — Rectangle. Метод __init__ принимает две точки — левый верхний и правый нижний угол. Каждая точка представлена экземпляром класса Point. Реализуйте методы вычисления площади и периметра прямоугольника.

  6. Добавьте в класс Rectangle метод has_point. Метод принимает точку на плоскости и возвращает True, если точка находится внутри прямоугольника и False в противном случае.

  7. Создайте класс фигура — Figure. Метод __init__ принимает число — количество строительных блоков фигуры. Каждый объект будет состоять из заданного количества строительных блоков. У класса должен быть метод print_figure, который печатает фигуру. С использованием этого класса реализуйте программу, которая будет “строить стену” из случайного количества строительных блоков.

Пример:

Строительный блок:
         _
        |_|
Вывод:
          _  _  _
         |_||_||_|
          _  _
         |_||_|
          _  _  _  _
         |_||_||_||_|

Инкапсуляция

В объектно-ориентированных языках программирования есть спецификаторы, ограничивающие доступ к аттрибутам. Главной задачей является отделение деталей реализации логики объекта от того как с ним надо взаимодействовать.

В языке Python в отличие от многих других языков вместо ключевых слов используется знак нижнего подчёркивания.

public - Данный аттрибут доступен всем:

class Person:
  def __init__(self, name):
    self.name = name    # публичный аттрибут

p = Person("John")
p.name = "Mark"

private - Аттрибут сокрыт от посторонних глаз и доступен только самому объекту:

class Person:
  def __init__(self, name, age):
    self.name = name
    self.set_age(age)

  def get_age(self):
    return self.__age

  def set_age(self, age):
    if age >= 0:
      self.__age = int(age)  # __age - приватный аттрибут
    else:
      self.__age = 0
      print("Возраст не может быть отрицательным!")

p = Person("John", 19)
print(p.get_age()) # 19

p.set_age(20)
print(p.get_age()) # 20

p.__age = 21 # Error
p._Person__age = 21
print(p.get_age()) # 21

Задачи

  1. Описать класс десятичного счётчика. Он должен обладать внутренней переменной, хранящей текущее значение, методами повышения значения (increment) и понижения (decrement), получения текущего значения get_counter. Учесть, что счётчик не может опускаться ниже 0.

  2. Создать классы для травоядного животного и травы. Животное должно уметь поедать траву, если испытывает голод, в противном случае отказываться от лакомства. Трава должна обладать питательностью, в зависимости от которой животное будет насыщаться.

  3. Создать класс для часов. Должна быть возможность установить время при создании объекта. Также необходимо реализовать методы, с помощью которых можно добавлять по одной минуте/секунде или по одному часу к текущему времени. Помнить, что значения минут и секунд не могут превышать 59, а часов 23.

  4. Доработать предыдущую задачу, чтобы можно было складывать двое часов друг с другом. Для перегрузки оператора + использовать метод __add__(self, other).

Основы PyGame

Pygame — библиотека, предназначенная для разработки мультимедийных приложений с графическим интерфейсом, например игр.

Документация, обучающие материалы и дополнительная информация доступна разработчикам на сайте проекта: https://www.pygame.org/docs/

Начало работы

Начнем знакомство с библиотекой непосредственно с разбора примера простого приложения:

import pygame
import sys

pygame.init()

screen = pygame.display.set_mode((1200, 800))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

В первую очередь импортируем модуль pygame в наш файл с исходным кодом:

import pygame

Затем вызываем функцию init() для подготовки модулей pygame к работе:

pygame.init()

После этого создаем графическое окно, передав в качестве аргумента в функцию set_mode() его разрешение в виде пары целых чисел. В свою очередь функция вернет нам объект типа Surface, используемый для представления изображений:

screen = pygame.display.set_mode((1200, 800))

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

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

После того как ожидаемое событие наступило, завершаем работу с библиотекой pygame вызовом функции pygame.quit() и нашей программы вызовом функции exit() из модуля sys.

Рисование геометрических фигур

Разместим в окне нашего приложения прямоугольник. Прямоугольные объекты представлены типом Rect:

Rect(left, top, width, height)
Rect((left, top), (width, height))

Для создания объекта этого типа нам необходимо указать координаты левого верхнего угла прямоугольника и длины его сторон:

r = Rect(0, 0, 100, 200)

Обратите внимание, что начало координат (0, 0) находится в левом верхнем углу окна.

В библиотеке pygame функции отображения геометрических фигур находятся в модуле draw. Нарисуем прямоугольник c помощью функции rect():

rect(Surface, color, Rect, width=0) -> Rect

Для этого передадим в функцию в качестве аргументов поверхность, на которой мы размещаем прямоугольник, его цвет, сам прямоугольник и толщину линии — стороны прямоугольника. Если толщина равна нулю прямоугольник закрашивается сплошным цветом.

Рассмотрим готовый пример:

import pygame
import sys

pygame.init()

screen = pygame.display.set_mode((1000, 800))
r = pygame.Rect(50, 50, 100, 200)
pygame.draw.rect(screen, (255, 0, 0), r, 0)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.flip()

Обратите внимание на последнюю строку нашей программы. На самом деле графические объекты которые мы хотим разместить на основном экране сначала попадают в специальный буфер. Чтобы отобразить изменения стали видны вызываем функцию flip().

Прочие функции для рисования графических фигур

pygame.draw.line(Surface, color, start_pos, end_pos, width=1)

Нарисовать линию на поверхности Surface, цветом color, с началом в точке start_pos, концом в точке end_pos и толщиной линии width.

pygame.draw.lines(Surface, color, closed, pointlist, width=1)

Нарисовать линию, соединяющую точки из последовательности pointlist на поверхности Surface, цветом color, с толщиной линии width. Каждая точка представлена парой координат. Если параметр closed равен True, конечная точка соединяется с начальной.

pygame.draw.circle(Surface, color, pos, radius, width=0)

Нарисовать окружность на поверхности Surface, цветом color, с центром в точке pos и радиусом radius. Если толщина линии width равна нулю, окружность закрашивается.

pygame.draw.ellipse(Surface, color, Rect, width=0)

Нарисовать эллипс, ограниченный прямоугольником Rect, на поверхности Surface, цветом color. Если толщина линии width равна нулю, эллипс закрашивается.

pygame.draw.polygon(Surface, color, pointlist, width=0)

Нарисовать многоугольник по точкам из последовательности pointlist на поверхности Surface, цветом color, с толщиной линии width. Каждая точка представлена парой координат. Если толщина линии width равна нулю многоугольник закрашивается.

Цвет

Цвета в библиотеке pygame представлены в соответствии с моделью RGB: https://ru.wikipedia.org/wiki/RGB

Значение для цвета можно задать тройкой чисел, каждое из которых лежит в диапазоне от 0 до 255. Первое значение в последовательности определяет, какое количество красного содержится в данном оттенке, второе - зеленого, третье - голубого. Чем меньше значение числа, тем темнее будет оттенок. Например, красный цвет можно представить как (255, 0, 0), белый как (255, 255, 255), а черный как (0, 0, 0).

Помимо этого, в модуле color из библиотеки pygame содержится словарь THECOLORS, ключами которого являются названия различных цветовых оттенков. Подключить его можно с помощью команды:

from pygame.color import THECOLORS

Закрасим основной экран c помощью метода fill():

screen = pygame.display.set_mode((1200, 800))
screen.fill(THECOLORS['orange'])

Текст и шрифты

При работе с текстом мы будем использовать шрифты - группы символов объединенных по стилистическому или иному признаку. Шрифты в библиотеке pygame представлены типом Font

Чтобы создать объект Font на основе имеющегося в системе шрифта вызовем следующую функцию:

SysFont(name, size, bold=False, italic=False)

С помощью параметра name передаем в функцию имя шрифта, параметр size - размер шрифта в пунктах. Параметры bold и italic отвечают за начертание шрифта.

Список имеющихся в системе шрифтов можно получить с помощью функции get_fonts():

pygame.font.get_fonts() -> list of strings

Далее, с помощью метода render() нашего объекта типа Font получаем изображение с текстом, которое передаем на вход методу blit() для отрисовке на нашем основном экране:

screen = pygame.display.set_mode(size)
screen.fill(THECOLORS['white'])
font = pygame.font.SysFont('couriernew', 40)
text = font.render(str('HELLO'), True, THECOLORS['green'])
screen.blit(text, (50, 50))

Текст размещается в на основном экране по координатам (50, 50)

Задания

1. Используя функции для работы с графикой библиотеки pygame, нарисуйте дом с квадратным основанием и треугольной крышей.

2. Используя функции для работы с графикой библиотеки pygame, нарисуйте белый флаг с олимпийскими кольцами.

3. Разработайте программу, которая разбивает основное игровое окно на клетки заданного размера.

4. Доработайте программу так, чтобы в каждой клетке был записан её порядковый номер.

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

Обработка ввода и анимации

События

Взаимодействие пользователя с компьютером основано на событиях, любые действия производимые пользователем порождают события - движение мыши, нажатия клавиш, специальных кнопок. Внутри библиотеки PyGame есть инструменты для обратки событий, которые происходят внутри приложений.

Мы с вами уже знакомы с методом получения всех произошедших событий - pygame.event.get(), который возвращает события, произошедшие с последнего обращения.

Помимо событий выхода из приложения pygame.QUIT, есть множество других - например, нажатия клавиш pygame.KEYDOWN или отпускания pygame.KEYUP.

Рассмотрим взаимодействие с событиями на примере небольшой программы, в которой по нажатию клавиш показывается квадрат:

import sys
import pygame

pygame.init()

screen = pygame.display.set_mode((640, 480))
rect = pygame.Rect(40, 40, 120, 120)
color = (0, 0, 0)   

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            color = (255, 255, 255)

    pygame.draw.rect(screen, color, rect, 0)
    pygame.display.flip()

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

События

Когда генерируется

KEYDOWN

При нажатии клавиш

KEYUP

При отпускании клавиш

QUIT

При нажатии кнопки закрытия программы

MOUSEMOTION

При движении мыши

Обработка нажатий клавиш

Когда мы нажимаем клавишу, в систему передаётся не только информация о том, что какая-то кнопка нажата, но и её код.

Есть два способа получить нажатые клавиши:
  1. pygame.event.get()

  2. pygame.key.get_pressed()

С первым мы уже знакомы, поэтому стоит внимательнее рассмотреть второй. Он позволяет получить список клавиш, которые нажаты в данный момент в виде кортежа булевых значений. Чтобы узнать нажата ли интересующая нас кнопка, необходимо проверить значение, которе содержится в данном кортеже:

keys = pygame.key.get_pressed()
if keys[pygame.K_RETURN]:
    print("Нажата клавиша enter")

Перемещение объектов

Умея получать от пользователя ввод, мы можем реализовать движения наших фигур на экране:

import sys
import pygame

pygame.init()

screen = pygame.display.set_mode((640, 480))
rect = pygame.Rect(40, 40, 120, 120)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                rect.move_ip(-40, 0)
            elif event.key == pygame.K_RIGHT:
                rect.move_ip(40, 0)
            elif event.key == pygame.K_UP:
                rect.move_ip(0, -40)
            elif event.key == pygame.K_DOWN:
                rect.move_ip(0, 40)

    pygame.draw.rect(screen, (255, 0, 0), rect, 0)

    pygame.display.flip()

Для движения объектов используются методы move() и move_ip(), которыми обладают объекты, созданные с помощью функций из pygame.draw. Первый создаёт новую фигуру такого же типа, находящуюся по заданному смещению, второй непосредственно изменяет положение имеющейся фигуры.

Запустив данный код, вы можете заметить, что при перемещении фигуры от неё остаётся “след”. Это связано с тем, что при перемещении объекта, мы его не перемещаем на экране, а рисуем на новом месте поверх старого кадра.

Чтобы избежать данной проблемы, надо добавить вызов метода fill() у нашего экрана, на котором мы рисуем и передать ему цвет, которым надо закрасить фон. Данное действие надо проводить каждый раз перед отрисовкой кадра:

# здесь могла быть ваша проверка событий
screen.fill((0, 0, 0))
pygame.draw.rect(screen, (255, 0, 0), rect, 0)
pygame.display.flip()

Использование спрайтов

Спрайт - двумерное изображение, используемое в играх.

pygame.image.load(path)

Функция для загрузки спрайта из картинки. Path - путь до изображения, возвращает объект типа Surface, который можно использовать для рисования.

Для отрисовки спрайта на экране надо вызвать метод blit() у поверхности на которой производится отрисовка и передать объект спрайта вместе с координатами на которых необходимо отрисовать:

screen = pygame.display.set_mode((640, 480))
sprite = pygame.image.load("sprite.png")

screen.blit(sprite, (20, 20))
pygame.quit()

Анимации

В pygame анимации создаются при помощи набора спрайтов, которые последовательно отрисовываются:


animation_set = [pygame.image.load(f"r{i}.png") for i in range(1, 6)]

window = pygame.display.set_mode((640, 480))

clock = pygame.time.Clock()
i = 0
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    window.fill((0,0,0))
    window.blit(animation_set[i // 12], (100, 20))
    i += 1
    if i == 60:
        i = 0

    pygame.display.flip()
    clock.tick(60)

Создаём список спрайтов, каждый из которых будет отдельным кадром анимации:

animation_set = [pygame.image.load(f"r{i}.png") for i in range(1, 6)]

Создаём часы, для ограничения количества кадров в секунду:

clock = pygame.time.Clock()

Вспомогательная переменная, которая поможет выбирать нужную анимацию в зависимости от номера кадра:

i = 0

Выбор анимации в зависимости от номера кадра и его отрисовка:

window.blit(animation_set[i // 12], (100, 20))

Изменение переменной, помогающей выбрать нужный кадр:

i += 1
if i == 60:
   i = 0

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

clock.tick(60)

Задания

  1. Написать программу, которая будет писать в консоль названия нажатых клавиш. Реализовать поддержку enter, space, w, a, s, d, esc.

  2. С помощью циклов, используя квадрат 10х10 пикселей и его след, нарисовать рамку 100х100 пикселей.

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

  4. Доработать программу, чтобы квадрат при каждом движении менял свой цвет на случайный.

  5. Реализовать анимацию движения персонажа. При движении влево или вправо должны показываться соответствующие анимации. Кадры для них взять из архива animations.zip

Обработка столкновений

  1. Реализуйте игровую сцену, состоящую из движущейся цели и пушки, стреляющей снарядами.

"""
+-----------------------+
|   ||||||              | <- target
|                       |
|                       |
|           *           | <- bullet
|                       |
|                       |
|          /'\          | <- cannon
+-----------------------+
"""

import random
import sys

import pygame
from pygame.color import THECOLORS

pygame.init()

WIDTH = 640
HEIGHT = 480

screen = pygame.display.set_mode((WIDTH, HEIGHT))


class Cannon:
    def __init__(self):
        # TODO(1.1): создайте атрибуты пушки:
        #  * Цвет
        #  * Список точек
        #  Пусть пушка отображается как равнобедренный треугольник с высотой
        #  и основанием по 50px. Отображается в середине окна
        #  на нижней границе, см. схему в начале файла.
        ...

    def draw(self):
        # TODO(1.2): отобразите созданную в __init__ последовательность точек
        #  заданным цветом.
        ...


class Bullet:
    def __init__(self):
        # TODO(2.1): создайте атрибуты снаряда.
        #  * Центр окружности снаряда
        #  * Радиус
        #  * Цвет
        #  * Скорость (для тестов использовать значение 3)
        ...

    def draw(self):
        # TODO(2.2): отобразите снаряд.
        ...

    def move(self):
        # TODO(2.3): реализуйте перемещение снаряда.
        #  Для этого нужно создать его новый центр со смещением speed по оси OY
        #  к началу коориднат.
        ...


class Target:
    def __init__(self):
        # TODO(3.1): создайте атрибуты мишени.
        #  * Цвет
        #  * Скорость
        #  * Прямоугольник
        ...

    def draw(self):
        # TODO(3.2): отобразите мишень.
        ...

    def move(self):
        # TODO(3.3): реализуйте движение мишени.
        #  При достижении края окна мишень должна менять направление движения
        #  на противположное. Это можно реализовать сменой знака сокрости.
        ...


colors = list(THECOLORS.values())
def get_random_color():
    return random.choice(colors)


cannon = Cannon()
target = Target()
bullet = Bullet()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(THECOLORS['black'])

    target.move()
    bullet.move()

    # TODO(2.4): если снаряд достиг верхней границы окна, создать новый снаряд.

    # TODO(4.1): если мишень и снаряд пересеклись, сменить цвет мишени на
    #  случайный, создать новй снаряд.
    #  Для определения пересечения используйте метод прямоугольника:
    #    Rect.collidepoint(point)

    cannon.draw()
    target.draw()
    bullet.draw()

    pygame.display.flip()
    pygame.time.wait(33)
  1. Реализуйте простейший тир, в котором игрок должен кликать по цели.

import math
import random
import sys

import pygame
from pygame.color import THECOLORS

pygame.mixer.init(22050, -16, 2, 64)
pygame.init()

WIDTH = 640
HEIGHT = 480

screen = pygame.display.set_mode((WIDTH, HEIGHT))

color = THECOLORS['purple1']

circle_radius = 50


def distance(p1, p2):
    # TODO(3.3): Реализуйте функцию, которая вычисляет
    #  расстояние между точками p1 и p2.
    ...


def point_in_circle(p, circle_center, circle_radius):
    # TODO(3.2): Реализуйте функцию, которая возвращает True,
    #  если точка находится внутри круга.
    #  Для полноценной работы функции вам понадобится
    #  реализовать функцию distance, но написать определение
    #  принадлежности точки кругу вы можете уже сейчас.
    ...


def place_circle():
    # TODO(1.1): Функция должна вернуть кортеж, состоящий из
    #   координат центра круга: (x, y)
    ...

# TODO(1.2): инициализируйте центр круга
circle_center = ...

# TODO(5.1): Загрузите звук выстрела.
#  Воспользуйтесь конструктором
#  pygame.mixer.Sound(file_path: str) -> Sound
shot = ...

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        # TODO(2.1): Обработайте событие нажатия кнопки мыши
        #  pygame.MOUSEBUTTONDOWN
        # TODO(2.2): При нажатии кнопки мыши смените цвет круга.
        # TODO(3.1): Доработайте приложение так, чтобы круг менял цвет только
        #  если вы кликаете по нему. Для этого вам понадобирся реализовать
        #  функции point_in_circle и distance.
        # TODO(4.1): доработайте приложение так, чтобы при
        #  клике по кругу он появлялся в случайной точке
        #  экрана.
        # TODO(5.2): Воспроизведите звук выстрела в случае попадания по кругу.
        #  Используйте метод play() объекта класса Sound.
        # TODO(6.1): Реализуйте подсчет очков. Если игрок попал в круг за
        #  секунду, то он получает 100 очков. За 2 секунды - 50. Дольше - 1.
        ...

    screen.fill(THECOLORS['black'])

    # TODO(1.3) Нарисуйте круг выбранного цвета.
    ...

    pygame.display.flip()
    pygame.time.wait(33)
  1. Реализуйте движущийся шар, отскакивающий от стен.

import math
import sys

import pygame
from pygame.color import THECOLORS

pygame.init()

WIDTH = 1280
HEIGHT = 800

screen = pygame.display.set_mode((WIDTH, HEIGHT))

circle_center = (WIDTH // 2, HEIGHT // 2)
circle_radius = 50
circle_color = THECOLORS['purple2']

SPEED = 20

current_angle = -10


def get_move(angle):
    angle = angle / 180. * math.pi
    return (
        int(SPEED * math.cos(angle)),
        int(SPEED * math.sin(angle)))


def move_circle(center, move):
    # TODO(1): функция возвращает новый центр окружности после смещения.
    ...


def get_angle(center):
    # TODO(2): Функция принимает текущий центр круга и определяет,
    #  под каким углом он должен продолжать движение.
    ...

move = get_move(current_angle)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill(THECOLORS['black'])

    # TODO(3):
    #  * Вычислить угол движения круга.
    #  * Вычислить вектор движения
    #  * Вычислить новый центр окружности

    pygame.draw.circle(screen, circle_color, circle_center, circle_radius)

    pygame.display.flip()
    pygame.time.wait(33)

Звук выстрела: shot.wav.

Лабиринт

Каркас проекта и руководство в архиве: maze.zip

Змейка

Скачать шаблон: snake.py

import pygame
import random
import sys


# Размеры окна в пикселях
WINDOW_WIDTH = 640
WINDOW_HEIGHT = 480

CELL_SIZE = 20

# Размеры сетки в ячейках
WIDTH = int(WINDOW_WIDTH / CELL_SIZE)
HEIGHT = int(WINDOW_HEIGHT / CELL_SIZE)

# Цвета
BG_COLOR = (0, 0, 0)
GRID_COLOR = (40, 40, 40)
APPLE_COLOR = (255, 0, 0)
APPLE_OUTER_COLOR = (155, 0, 0)
SNAKE_COLOR = (0, 255, 0)
SNAKE_OUTER_COLOR = (0, 155, 0)


UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'

HEAD = 0


FPS = 15


class Cell:
    def __init__(self, x, y):
        self.x = x
        self.y = y


def main():
    global FPS_CLOCK
    global DISPLAY

    pygame.init()
    FPS_CLOCK = pygame.time.Clock()
    DISPLAY = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    pygame.display.set_caption('Wormy')

    while True:
        # Мы всегда будем начинать игру с начала. После проигрыша сразу
        # начинается следующая.
        run_game()


def run_game():
    # TODO(2.1): создать яблоко в позиции (20, 10)

    # TODO(3.1): создать змейку. Пусть она состоит из трех ячеек
    #  в строке 10 и столбцах 3, 4, 5.
    #  Какой тип данных удобен для представления змейки?

    # TODO(4.1): задать исходное направление движения змейки.
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                terminate()
            # TODO(7.1): обработайте событие pygame.KEYDOWN
            #  и при необходимости измените направление движения змейки.

        # TODO(5.1): если змейка достигла границы окна, завершить игру.
        #  Для проверки воспользуйтесь функцией snake_hit_edge.

        # TODO(8.1): если змейка задела свой хвост, завершить игру.
        #  Для проверки восппользуйтесь функцией snake_hit_self.

        # TODO(6.1): обработайте ситуацию столкновения змейки с яблоком.
        #  В этом случае нужно:
        #  * Увеличить размер змейки
        #  * Создать новое яблоко.

        # TODO(4.2): сдвинуть змейку в заданном направлении
        # TODO(2.2): передать яблоко в функцию отрисовки кадра
        # TODO(3.2): передать змейку в функцию отрисовки кадра
        draw_frame(None, None)
        FPS_CLOCK.tick(FPS)


def draw_frame(snake, apple):
    DISPLAY.fill(BG_COLOR)
    draw_grid()
    draw_snake(snake)
    draw_apple(apple)
    pygame.display.update()


def draw_grid():
    # TODO(1.2): нарисовать сетку.
    #  Шаг CELL_SIZE
    #  Цвет GRID_COLOR
    #  https://www.pygame.org/docs/ref/draw.html#pygame.draw.line
    ...


def draw_apple(apple):
    # TODO(2.3): нарисовать яблоко.
    ...


def draw_snake(snake):
    # TODO(3.3): нарисовать змейку.
    ...


def draw_cell(cell, outer_color, inner_color):
    # TODO(2.4): вспомогательная функция для рисования ячейки.
    #  Ячейка будет состоять из двух квадратов разных цветов:
    #  Больший квадрат закрашивается цветом outer_color,
    #  меньший - inner_color.
    #  Расстояние между внешним и внутренним квадратом
    #  принять за 4 пикселя.
    ...


def move_snake():
    # TODO(4.3): реализовать перемещение змейки на одну ячейку
    #  в заданном направлении.
    #  * Какие параметры будет принимать функция?
    #  * Из каких действий будет состоять перемещение змейки?
    ...


def get_snake_new_head():
    # TODO(4.4): реализовать функцию определения нового
    #  положения головы змейки.
    #  * Какие параметры будет принимать функция?
    #  * Что функция будет возвращать?
    ...


def snake_hit_edge():
    # TODO(5.2): функция возвращает True,
    #  если змейка пересекла одну из границ окна.
    ...


def snake_hit_apple():
    # TODO(6.2): функция возвращает True, если голова
    #  змейки находится в той же ячейке, что и яблоко.
    ...


def snake_grow():
    # TODO(6.3): предложите максимально простой
    #  способ увеличения длины змейки.
    ...


def new_apple():
    # TODO(6.4): функция возвращает случайную ячейку,
    #  в которой будет располагаться яблоко.
    #  Для генерации случайной координаты воспользуйтесь
    #  функцией random.randint(a, b)
    ...


def get_direction():
    # TODO(7.3): функция возвращает направление движения
    #  в зависимости от нажатой клавиши:
    #  * pygame.K_LEFT
    #  * pygame.K_RIGHT
    #  * pygame.K_UP
    #  * pygame.K_DOWN
    #  Если нажата клавиша противоположного направления движения,
    #  то не менять направление.
    ...

def snake_hit_self():
    # TODO(8.2): функция возвращает True, если голова змеи
    #  пересеклась хотя бы с одним блоком хвоста.
    ...


def terminate():
    pygame.quit()
    sys.exit()


if __name__ == '__main__':
    main()

Повторение (первое полугодие)

Задачи

  1. Цветовой микшер

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

  • если смешать красный и синий, то получится фиолетовый;

  • если смешать красный и желтый, то получится оранжевый;

  • если смешать синий и желтый, то получится зеленый.

Разработайте программу, которая предлагает пользователю ввести названия двух основных цветов для смешивания. Если пользователь вводит что-нибудь помимо названий “красный”, “синий” или “желтый”, то программа должна вывести сообщение об ошибке. В противном случае программа должна вывести название цвета, который получится в результате.

Пример 1:

Ввод:
  Введите первый цвет: желтый
  Введите второй цвет: красный

Вывод:
  Вы получите: оранжевый

Пример 2:

Ввод:
  Введите первый цвет: желтый
  Введите второй цвет: черный

Вывод:
  Один из основных цветов введён неверно!
  1. Расписание

На вход принимаем время начала первого урока, длительность урока, длительность перемен, выводим - расписание звонков на N уроков.:

Ввод:
  Начало первого урока (час:мин): 8:00
  Длительность урока, мин: 45
  Длительность перемен, мин: 10
  На сколько уроков нужно расписание: 4

Вывод:
  1 урок: 8:00 - 8:45
  2 урок: 8:55 - 9:40
  3 урок: 9:50 - 10:35
  4 урок: 10:45 - 11:30
  1. Зомби-апокалипсис

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

Ввод:
  Сколько зомби было к началу расчёта: 2
  Сколько каждый может заразить: 1
  На который день делаем расчёт: 4

Вывод:
  1 день: 2
  2 день: 4
  3 день: 8
  4 день: 16
  1. Сумма соседей

Нaпишите функцию, которая принимает список чисел одной строкой, а затем возвращает список, в котором вместо каждого элемента введённой строки указана сумма двух его cоседей. Для элeментов списка, являющиxся крайними, одним из соседей считается элемент, находящий на противоположном конце этого списка. Если на вход пришло только однo число, надо вывести его же.:

Ввод:
 1 3 5 6 10

Вывод:
 [13,6,9,15,7]
  1. Количество строк, слов и букв в файле

Нaпишите функцию, которая принимает на вход имя файла и считает количество строк, слов и букв в указанном файле.

Ввод:
  Введите имя файла: 2.txt

Вывод:
  Файл: 2.txt
  Строк: 10
  Слов: 60
  Символов: 500
  1. Двоичный (бинарный) поиск

Двоичный (бинарный) поиск - это поиск в упорядоченном массиве, главная идея которого - постоянно сужать диапазон поиска в 2 раза, пока мы не найдём нужное значение.

Нaпишите 2 функции:

  • Функция для линейного поиска в списке: на вход подаётся число, которое последовательно сравниваем с каждым элементом массива по порядку. На выходе получаем индекс заданного числа, если оно есть в списке.

  • Функция для бинарного поиска в списке: список нужно отсортировать, а затем сравниваем число не с каждым элементом списка, а каждый раз только со средним элементом. После чего сужаем диапазон поиска. Продолжаем, пока не найдём нужный элемент.

Посмотреть логику работы алгоритма можно на видео

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

  1. Имена

Есть список списков с именами детей нескольких классов школы, нужно сделать словарь, в котором “ключом” будет имя ребёнка, а значением - количество детей с таким именем во всех классах школы.:

Ввод:
  school_list = [['Таня','Ваня','Аня','Ира','Женя','Артём'],
                 ['Таня','Маша','Аня','Витя','Антон'],
                 ['Галя','Вова','Аня','Ира']]

Вывод:
  {'Таня': 2,
   'Ваня': 1,
   'Аня': 3,
   'Ира': 2,
   'Женя': 1,
   'Артём': 1,
   'Маша': 1,
   'Витя': 1,
   'Антон': 1,
   'Галя': 1,
   'Вова': 1}
  1. Словарь

Есть список со словарями, в каждом словаре ключ - это название языка, а значение - слово на этом языке, необходимо разделить этот словарь на несколько файлов, в каждом из которых будет хранится значение слова на русском языке, а через дефис - значение этого слова на другом языке из словаря. Название файла должно соответствовать языку:

Ввод:
  translation = [{'ru':'яблоко','en':'apple','es': 'manzana'},
                 {'ru':'помидор','en':'tomato','es': 'tomate'}]

Вывод:
  1 файл en.txt:
  яблоко - apple
  помидор - tomato

  2 файл es.txt:
   яблоко - manzana
   помидор - tomate
  1. Казино

Игроки бросают по 2 игральные кости несколько раз. Результы суммируются и побеждает тот, кто набрал наибольшее количество очков. Напишите функцию, которая будет определять победителя. Если результат одинаковый, то побеждает тот, кто выкинул большую сумму в последнем раунде. Функция принимает на вход количество игроков, количество раундов и выводит ход игры (броски в каждом раунде) и победителя. На каждой игральной кости можно выбросить число от 1 до 6:

Ввод:
 Количество игроков: 2
 Количетсво раундов: 2

Вывод:
 Раунд 1 Игрок 1: 2 - 4
 Раунд 1 Игрок 2: 1 - 5
 Раунд 2 Игрок 1: 3 - 2
 Раунд 2 Игрок 2: 2 - 4
 ______________________
 Итоговый счёт:
 Игрок 1 - 11
 Игрок 2 - 12

 Победил Игрок 2

Самостоятельная работа

  1. Условия

Пользователь вводит 3 числа одной строкой через пробел, нужно вывести наибольшее из этих чисел.:

Ввод:
  Введите числа через пробел: 1 2 3

Вывод:
  Наибольшее число: 3

*Усложнение: Запрашиваем у пользователя длину списка. Генерим числа с помощью библиотеки random и складываем их в список заданной длины. Потом ищем в списке максимальное число и выводим его.

  1. Словари

Пользователь вводит фразу, необходимо поместить её в словарь, в котором ключом будет символ, а значением - сколько раз данный символ встречается во фразе.:

Ввод:
  Введите фразу: Hello, Python

Вывод:
  {'H': 1, 'e': 1, 'l': 2, 'o': 2, ',': 1, ' ': 1, 'P': 1, 'y': 1, 't': 1, 'h': 1, 'n': 1}

*Усложнение: Вводим текст (ещё более сложный вариант - читать текст из файла), разбиваем его на слова и показываем, сколько раз каждое слово встречается в тексте.