Вы находитесь на странице: 1из 96

Практическая работа №1. Знакомство с инструментарием разработки.

Арифметические операции.
После загрузки и установки python открываем IDLE (среда разработки
на языке Python, поставляемая вместе с дистрибутивом).
Запускаем IDLE (изначально запускается в интерактивном режиме),
после чего уже можно начинать писать первую программу. Традиционно,
первой программой у нас будет "hello world".
Чтобы написать "hello world" на python, достаточно всего одной
строки:

print("Hello world!")

Вводим этот код в IDLE и нажимаем Enter. Результат виден на рисунке


ниже:

Для того, чтобы создать новое окно, в интерактивном режиме IDLE


выберите File → New File (или нажмите Ctrl + N).

В открывшемся окне введите следующий код:


name = input("Как Вас зовут? ")
print("Привет,", name)

Первая строка печатает вопрос ("Как Вас зовут? "), ожидает, пока вы не
напечатаете что-нибудь и не нажмёте Enter и сохраняет введённое значение в
переменной name.
Во второй строке мы используем функцию print для вывода текста на
экран, в данном случае для вывода "Привет, " и того, что хранится в
переменной "name".
Теперь нажмём F5 (или выберем в меню IDLE Run → Run Module) и
убедимся, что то, что мы написали, работает. Перед запуском IDLE
предложит нам сохранить файл. Сохраним туда, куда вам будет удобно,
после чего программа запустится.
Вы должны увидеть что-то наподобие этого (на скриншоте слева - файл
с написанной вами программой, справа - результат её работы):

Синтаксис языка Python, как и сам язык, очень прост.


Синтаксис
 Конец строки является концом инструкции (точка с запятой не
требуется).
 Вложенные инструкции объединяются в блоки по величине
отступов. Отступ может быть любым, главное, чтобы в пределах одного
вложенного блока отступ был одинаков. И про читаемость кода не забывайте.
Отступ в 1 пробел, к примеру, не лучшее решение. Используйте 4 пробела
(или знак табуляции, на худой конец).
 Вложенные инструкции в Python записываются в соответствии с
одним и тем же шаблоном, когда основная инструкция завершается
двоеточием, вслед за которым располагается вложенный блок кода, обычно с
отступом под строкой основной инструкции.

Несколько специальных случаев


 Иногда возможно записать несколько инструкций в одной строке,
разделяя их точкой с запятой:

a = 1; b = 2; print(a, b)

Но не делайте это слишком часто! Помните об удобочитаемости. А


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

 if (a == 1 and b == 2 and
 c == 3 and d == 4): # Не забываем про двоеточие
print('spam' * 3)

 Тело составной инструкции может располагаться в той же строке,


что и тело основной, если тело составной инструкции не содержит составных
инструкций. Ну я думаю, вы поняли :). Давайте лучше пример приведу:

if x > y: print(x)

Типы данных и приоритеты операций в языке Python


В языке Python выделяют несколько типов данных: целые числа, числа
с плавающей точкой(вещественные), строки, логический тип. 
Тип каждой переменной может динамически изменяться по ходу выполнения
программы. Определить, какой тип имеет переменная, можно с помощью
команды type()
Целое число в Python имеет тип int. Оно записывается как
последовательность цифр, перед которой также может стоять знак минус.
Основные операции с целыми числами:
 A + B — сумма;
 A - B — разность;
 A * B — произведение;
 A / B — частное, (результатом этого действия является
вещественное число, даже если A нацело делится на B);
 A + B — сумма;
 A - B — разность;
 A % B — взятие остатка от деления A на B;
 A / / B — взятие целой части от деления A на B
 A * * B — возведение в степень.

Приоритеты операций
Приоритеты операций в Python совпадают с приоритетом операций в
математике, а именно:
 Выполняются возведения в степень справа налево, то есть 3 * * 3 * *
3 это 3 * * (3 * * 3).
 Выполняются унарные минусы (отрицания).
 Выполняются умножения и деления слева направо. Операции
умножения и деления имеют одинаковый приоритет.
 Выполняются сложения и вычитания слева направо. Операции
сложения и вычитания имеют одинаковый приоритет.
Для изменения порядка действий нужно использовать скобки.
Вещественное число в Python имеет тип float. Оно записывается как
последовательность цифр, перед которой также может стоять знак минус. В
качестве разделителя целой и дробной части используется точка.
Основные операции с вещественными числами:
 A + B — сумма;
 A - B — разность;
 A * B — произведение;
 A / B — частное, (результатом этого действия является
вещественное число, даже если A нацело делится на B);
 A % B — взятие остатка от деления A на B, (подразумевается, что
неполное частное является целым числом);
 A B — взятие целой части от деления A на B, (подразумевается, что
неполное частное является целым числом);
 A * * B — возведение в степень.
Приоритеты операций Приоритеты операций совпадают с
приоритетами операций с целыми числами.
Строки в Python имеют тип str. Строкой называется
последовательность символов: букв, цифр, знаки препинания и т.д.
Основные операции со строками
 A + B — конкатенация (строка B приписывается к строке A);
 A * n — повторение n раз, значение n должно быть целого типа.

Преобразование типов в Python


Иногда бывает полезно целое число записать как строку. И, наоборот,
если строка состоит из цифр, то полезно эту строку представить в виде числа,
чтобы дальше можно было выполнять арифметические операции с ней. Для
этого используются функции, название которых совпадает с именем типа, то
есть int, float, str. Например, int(‘123’) вернет целое число 123, str(123) вернет
строку ‘123’, а следующая инструкция:
print(str(2 + 2) * int('2' + '2'))
выведет символ “4”, повторенный 22 раза.
Функция int также поможет превратить дробное число в целое,
отбросив дробную часть:
int(12.3) = 12, int(-12.3) = 12.
Еще один полезный пример использования — преобразование строки в
список букв:
list('abc') = ['a', 'b', 'c'] 
Также преобразование типов активно используется с функцией map и
генераторами, например, numbers = list(map(int, input().split()))

Целочисленная арифметика
Для целых чисел определены ранее рассматривавшиеся операции +, -, *
и * *. Операция деления / для целых чисел всегда возвращает значение типа
float. Также функция возведения в степень возвращает значение типа float,
если показатель степени — отрицательное число.
Но есть и специальная операция целочисленного деления, выполняющегося с
отбрасыванием дробной части, которая обозначается . Она возвращает целое
число: целую часть частного. Например:
print(17 3)
выведет 5
print(-17 3)
выведет(-6)
Другая близкая ей операция: это операция взятия остатка от деления,
обозначаемая %:
print(17 % 3) 
выведет 2
print(-17 % 3) 
выведет 1
Формальное определение деления с остатком такое. Если есть два
числа A и B (при этом B не равно 0), то деление A на B с остатком — это
нахождение таких целых чисел Q (частное) и R (остаток), что 
A=B*Q+R
При этом если B > 0, то 0 ⇐ R < B, а если B < 0, то B < R ⇐ 0 (то есть
остаток имеет такой же знак, что и делитель).
Деление с остатком в других языках программирования для
отрицательных делимого или делителя может давать другой результат. Это
связано с особенностью реализации операции деления в процессоре.
Одно из наиболее распространенных применений операции деления с
остатком — это анализ цифр десятичной записи числа. А именно, деление
числа нацело на 10 (операция n 10) — это отбрасывание последней цифры
десятичной записи числа, а остаток от деления на 10 (n % 10) — это
последняя цифра числа.
Ввод-вывод в Python
Для считывания строки со стандартного ввода используется функция
input(), которая считывает строку с клавиатуры и возвращает значение
считанной строки, которое сразу же можно присвоить переменным: 
a = input()
b = input()
Правда, функция input возвращает текстовую строку. Если нужно
сделать так, чтобы переменные имели целочисленные значения, то сразу же
после считывания выполним преобразование типов при помощи фунцкии int,
и запишем новые значения в переменные a и b:
a = int(a)
b = int(b)
Можно объединить считывание строк и преобразование типов, если
вызывать функцию int для того значения, которое вернет функция input():
a = int(input())
b = int(input())
Сложнее считать значения переменных, если они записаны в отдельной
строке. Здесь нужно применить к считанной строке метод split(), который
разделяет строку на части по одному или двум пробелам. Затем результат
выполнения этой функции присвоим кортежу из двух или нескольких чисел.
Например, если в строке вводятся два числа через пробел, то считать их
можно так:
a, b = input().split()
a = int(a)
b = int(b)
Аналогично, три переменные можно считать, записав слева от
оператора присваивания кортеж из трех переменных: a, b, c = input().split()
Можно также сразу же преобразовать считанные значения в числовой тип
(например, int), если воспользоваться функцией map, которая применяет к
каждому элементу списка заданную функцию (для преобразования к типу int
нужно, соответственно, задать функцию int для применения к каждому
элементу). Для начала можно просто запомнить эту конструкцию:
a, b, c = map(int, input().split())
Вывод данных 
Для вывода данных используется функция print может выводить не
только значения переменных, но и значения любых выражений. Например,
допустима запись print(2 + 2 ** 2). Также при помощи функции print можно
выводить значение не одного, а нескольких выражений, для этого нужно
перечислить их через запятую:
a = 1 b = 2 print(a, '+', b, '=', a + b)
В данном случае будет напечатан текст 1 + 2 = 3: сначала выводится
значение переменной a, затем строка из знака “+”, затем значение
переменной b, затем строка из знака “=”, наконец, значение суммы a + b.
Обратите внимание, выводимые значение разделяются одним пробелом. Но
такое поведение можно изменить: можно разделять выводимые значения
двумя пробелами, любым другим символом, любой другой строкой,
выводить их в отдельных строках или не разделять никак. Для этого нужно
функции print передать специальный именованный параметр, называемый
sep, равный строке, используемый в качестве разделителя (sep —
аббревиатура от слова separator, т.е. разделитель). По умолчанию параметр
sep равен строке из одного пробела и между значениями выводится пробел.
Чтобы использовать в качестве разделителя, например, символ двоеточия
нужно передать параметр sep, равный строке ‘:’:
print(a, b, c, sep = ':')
Аналогично, для того, чтобы совсем убрать разделитель при выводе
нужно передать параметр sep, равный пустой строке:
print(a, '+', b, '=', a + b, sep = ' ')
Для того, чтобы значения выводились с новой строке, нужно в качестве
параметра sep передать строку, состоящую из специального символа новой
строки, которая задается так:
print(a, b, sep = '\n')
Символ обратного слэша в текстовых строках является указанием на
обозначение специального символа, в зависимости от того, какой символ
записан после него. Наиболее часто употребляется символ новой строки ‘\n’.
А для того, чтобы вставить в строку сам символ обратного слэша, нужно
повторить его два раза: ‘\\’.
Вторым полезным именованным параметром функции print является
параметр end, который указывает на то, что выводится после вывода всех
значений, перечисленных в функции print. По умолчанию параметр end равен
‘\n’, то есть следующий вывод будет происходить с новой строки. Этот
параметр также можно исправить, например, для того, чтобы убрать все
дополнительные выводимые символы можно вызывать функцию print так:
print(a, b, c, sep = , end = )

Задание
1. Даны катеты прямоугольного треугольника a и b. Найти его
гипотенузу c и периметр P.
2. Даны два круга с общим центром и радиусами R1 и R2 (R1 > R2).
Найти площади этих кругов S1 и S2, а также площадь S3 кольца, внешний
радиус которого равен R1, а внутренний радиус равен R2.
3. Известно, что X кг шоколадных конфет стоит A грн, а Y кг ирисок
стоит B грн. Определить, сколько стоит 1 кг шоколадных конфет, 1 кг
ирисок, а также во сколько раз шоколадные конфеты дороже ирисок.
4. Даны целые положительные числа A и B (A > B). На отрезке длины
A размещено максимально возможное количество отрезков длины B (без
наложений). Используя операцию деления нацело, найти количество
отрезков B, размещенных на отрезке AB.
5. Дано трехзначное число. Найти сумму и произведение его цифр.
6. Дано трехзначное число. Вывести число, полученное при прочтении
исходного числа справа налево.
7. Дано трехзначное число. В нем зачеркнули первую слева цифру и
приписали ее справа. Вывести полученное число.
8. Написать программу, позволяющую вычислить с помощью цикла:
5  6  7    (n  5) , где n задается с клавиатуры.
9. Написать программу, позволяющую вычислить с помощью цикла:
1  3  5  7    (2n  1) , где n задается с клавиатуры.
10. Написать программу, позволяющую вычислить с помощью цикла:
2  4  6    2n , где n задается с клавиатуры.
11. Написать программу, позволяющую вычислить с помощью цикла:
1  4  7    (3n  2) , где n задается с клавиатуры.
12. Написать программу, позволяющую вычислить с помощью цикла:
2  4  6    2n , где n задается с клавиатуры.
13. Написать программу, позволяющую вычислить с помощью цикла:
sin(1)  sin( 2)  sin(3)    sin(n) , где n задается с клавиатуры.
14. Написать программу, позволяющую вычислить с помощью цикла:
n  (n  1)  (n  1)    2  1 , где n задается с клавиатуры.
15. Написать программу, позволяющую вычислить с помощью цикла
сумму натуральных чисел отрезка [a, b]. (a и b задаются с клавиатуры).
16. Написать программу, позволяющую вычислить с помощью цикла
сумму четных чисел отрезка [a, b]. (a и b задаются с клавиатуры).
17. Написать программу, позволяющую вычислить с помощью цикла
сумму нечетных чисел отрезка [a, b]. (a и b задаются с клавиатуры).
Практическая работа №2. Базовые операторы языка. Срезы.
Синтаксис инструкции if
Сначала записывается часть if с условным выражением, далее могут
следовать одна или более необязательных частей elif, и, наконец,
необязательная часть else. Общая форма записи условной инструкции if
выглядит следующим образом:

if test1:
state1
elif test2:
state2
else:
state3

Простой пример (напечатает 'true', так как 1 - истина):

>>> if 1:
... print('true')
... else:
... print('false')
...
true

Чуть более сложный пример (его результат будет зависеть от того, что
ввёл пользователь):

a = int(input())
if a < -5:
print('Low')
elif -5 <= a <= 5:
print('Mid')
else:
print('High')
Конструкция с несколькими elif может также служить отличной
заменой конструкции switch - case в других языках программирования.

Проверка истинности в Python


 Любое число, не равное 0, или непустой объект - истина.
 Числа, равные 0, пустые объекты и значение None - ложь
 Операции сравнения применяются к структурам данных рекурсивно
 Операции сравнения возвращают True или False
 Логические операторы and и or возвращают истинный или ложный
объект-операнд
Логические операторы:

X and Y

Истина, если оба значения X и Y истинны.

X or Y

Истина, если хотя бы одно из значений X или Y истинно.

not X

Истина, если X ложно.


Трехместное выражение if/else
Следующая инструкция:

if X:
A=Y
else:
A=Z

довольно короткая, но, тем не менее, занимает целых 4 строки.


Специально для таких случаев и было придумано выражение if/else:

A = Y if X else Z
В данной инструкции интерпретатор выполнит выражение Y, если X
истинно, в противном случае выполнится выражение Z.

>>> A = 't' if 'spam' else 'f'


>>> A
't'

Цикл while
While - один из самых универсальных циклов в Python, поэтому
довольно медленный. Выполняет тело цикла до тех пор, пока условие цикла
истинно.

>>> i = 5
>>> while i < 15:
... print(i)
... i=i+2
...
5
7
9
11
13

Цикл for
Цикл for уже чуточку сложнее, чуть менее универсальный, но
выполняется гораздо быстрее цикла while. Этот цикл проходится по любому
итерируемому объекту (например строке или списку), и во время каждого
прохода выполняет тело цикла.

>>> for i in 'hello world':


... print(i * 2, end='')
...
hheelllloo wwoorrlldd
Оператор continue
Оператор continue начинает следующий проход цикла, минуя
оставшееся тело цикла (for или while)

>>> for i in 'hello world':


... if i == 'o':
... continue
... print(i * 2, end='')
...
hheellll wwrrlldd

Оператор break
Оператор break досрочно прерывает цикл.

>>> for i in 'hello world':


... if i == 'o':
... break
... print(i * 2, end='')
...
hheellll

Волшебное слово else


Слово else, примененное в цикле for или while, проверяет, был ли
произведен выход из цикла инструкцией break, или же "естественным"
образом. Блок инструкций внутри else выполнится только в том случае, если
выход из цикла произошел без помощи break.

>>> for i in 'hello world':


... if i == 'a':
... break
... else:
... print('Буквы a в строке нет')
...
Буквы a в строке нет

Взятие элемента по индексу


Как и в других языках программирования, взятие по индексу:

>>> a = [1, 3, 8, 7]
>>> a[0]
1
>>> a[3]
7
>>> a[4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range

Как и во многих других языках, нумерация элементов начинается с


нуля. При попытке доступа к несуществующему индексу возникает
исключение IndexError.
В данном примере переменная a являлась списком, однако взять
элемент по индексу можно и у других типов: строк, кортежей.
В Python также поддерживаются отрицательные индексы, при этом
нумерация идёт с конца, например:

>>> a = [1, 3, 8, 7]
>>> a[-1]
7
>>> a[-4]
1
>>> a[-5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Срезы
В Python, кроме индексов, существуют ещё и срезы.
item[START:STOP:STEP] - берёт срез от номера START, до STOP (не
включая его), с шагом STEP. По умолчанию START = 0, STOP = длине
объекта, STEP = 1. Соответственно, какие-нибудь (а возможно, и все)
параметры могут быть опущены.

>>> a = [1, 3, 8, 7]
>>> a[:]
[1, 3, 8, 7]
>>> a[1:]
[3, 8, 7]
>>> a[:3]
[1, 3, 8]
>>> a[::2]
[1, 8]

Также все эти параметры могут быть и отрицательными:

>>> a = [1, 3, 8, 7]
>>> a[::-1]
[7, 8, 3, 1]
>>> a[:-2]
[1, 3]
>>> a[-2::-1]
[8, 3, 1]
>>> a[1:4:-1]
[]

В последнем примере получился пустой список, так как START <


STOP, а STEP отрицательный. То же самое произойдёт, если диапазон
значений окажется за пределами объекта:
>>> a = [1, 3, 8, 7]
>>> a[10:20]
[]

Также с помощью срезов можно не только извлекать элементы, но и


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

>>> a = [1, 3, 8, 7]
>>> a[1:3] = [0, 0, 0]
>>> a
[1, 0, 0, 0, 7]
>>> del a[:-3]
>>> a
[0, 0, 7]

Модуль math – один из наиважнейших в Python. Этот модуль


предоставляет обширный функционал для работы с числами.
math.ceil(X) – округление до ближайшего большего числа.
math.copysign(X, Y) - возвращает число, имеющее модуль такой же,
как и у числа X, а знак - как у числа Y.
math.fabs(X) - модуль X.
math.factorial(X) - факториал числа X.
math.floor(X) - округление вниз.
math.fmod(X, Y) - остаток от деления X на Y.
math.frexp(X) - возвращает мантиссу и экспоненту числа.
math.ldexp(X, I) - X * 2i. Функция, обратная функции math.frexp().
math.fsum(последовательность) - сумма всех членов
последовательности. Эквивалент встроенной функции sum(), но math.fsum()
более точна для чисел с плавающей точкой.
math.isfinite(X) - является ли X числом.
math.isinf(X) - является ли X бесконечностью.
math.isnan(X) - является ли X NaN (Not a Number - не число).
math.modf(X) - возвращает дробную и целую часть числа X. Оба числа
имеют тот же знак, что и X.
math.trunc(X) - усекает значение X до целого.
math.exp(X) - eX.
math.expm1(X) - eX - 1. При X → 0 точнее, чем math.exp(X)-1.
math.log(X, [base]) - логарифм X по основанию base. Если base не
указан, вычисляется натуральный логарифм.
math.log1p(X) - натуральный логарифм (1 + X). При X → 0 точнее, чем
math.log(1+X).
math.log10(X) - логарифм X по основанию 10.
math.log2(X) - логарифм X по основанию 2. Новое в Python 3.3.
math.pow(X, Y) - XY.
math.sqrt(X) - квадратный корень из X.
math.acos(X) - арккосинус X. В радианах.
math.asin(X) - арксинус X. В радианах.
math.atan(X) - арктангенс X. В радианах.
math.atan2(Y, X) - арктангенс Y/X. В радианах. С учетом четверти, в
которой находится точка (X, Y).
math.cos(X) - косинус X (X указывается в радианах).
math.sin(X) - синус X (X указывается в радианах).
math.tan(X) - тангенс X (X указывается в радианах).
math.hypot(X, Y) - вычисляет гипотенузу треугольника с катетами X и
Y (math.sqrt(x * x + y * y)).
math.degrees(X) - конвертирует радианы в градусы.
math.radians(X) - конвертирует градусы в радианы.
math.cosh(X) - вычисляет гиперболический косинус.
math.sinh(X) - вычисляет гиперболический синус.
math.tanh(X) - вычисляет гиперболический тангенс.
math.acosh(X) - вычисляет обратный гиперболический косинус.
math.asinh(X) - вычисляет обратный гиперболический синус.
math.atanh(X) - вычисляет обратный гиперболический тангенс.
math.erf(X) - функция ошибок.
math.erfc(X) - дополнительная функция ошибок (1 - math.erf(X)).
math.gamma(X) - гамма-функция X.
math.lgamma(X) - натуральный логарифм гамма-функции X.
math.pi - pi = 3,1415926...
math.e - e = 2,718281...
Задание
Задание 1. Вычислите сумму ряда.
Задание 2. Пользователь вводит с клавиатуры любую фразу (от 10
символов). Используя срезы выведите на экран:
а) первые 4 символа,
б) последние 4 символа,
в) символ посередине,
г) символы с 3-го по 8-й.

Задание 3. Статистика по списку из 6 элементов.


Пользователь вводит с клавиатуры последовательно (через запятые) 6
целых десятичных чисел – элементов списка. Требуется:
а) вывести на экран 4-й элемент,
б) вывести все элементы в обратном порядке,
в) рассчитать и вывести на экран сумму и среднее арифметическое.

Практическая работа №3. Сложные типы данных.


Строки в Python - упорядоченные последовательности символов,
используемые для хранения и представления текстовой информации,
поэтому с помощью строк можно работать со всем, что может быть
представлено в текстовой форме.
Это первая часть о работе со строками, а именно о литералах строк.
Литералы строк
Работа со строками в Python очень удобна. Существует несколько
литералов строк, которые мы сейчас и рассмотрим.
Строки в апострофах и в кавычках

S = 'spam"s'
S = "spam's"

Строки в апострофах и в кавычках - одно и то же. Причина наличия


двух вариантов в том, чтобы позволить вставлять в литералы строк символы
кавычек или апострофов, не используя экранирование.
Экранированные последовательности - служебные символы
Экранированные последовательности позволяют вставить символы,
которые сложно ввести с клавиатуры.
Экранированная
Назначение
последовательность
\n Перевод строки

\a Звонок

\b Забой

\f Перевод страницы

\r Возврат каретки

\t Горизонтальная табуляция

\v Вертикальная табуляция

\N{id} Идентификатор ID базы данных Юникода

16-битовый символ Юникода в 16-ричном


\uhhhh
представлении
Экранированная
Назначение
последовательность
32-битовый символ Юникода в 32-ричном
\Uhhhh…
представлении

\xhh 16-ричное значение символа

\ooo 8-ричное значение символа

Символ Null (не является признаком конца


\0
строки)
"Сырые" строки - подавляют экранирование
Если перед открывающей кавычкой стоит символ 'r' (в любом
регистре), то механизм экранирования отключается.

S = r'C:\newt.txt'

Но, несмотря на назначение, "сырая" строка не может заканчиваться


символом обратного слэша. Пути решения:

S = r'\n\n\\'[:-1]
S = r'\n\n' + '\\'
S = '\\n\\n'

Строки в тройных апострофах или кавычках


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

>>> c = '''это очень большая


... строка, многострочный
... блок текста'''
>>> c
'это очень большая\nстрока, многострочный\nблок текста'
>>> print(c)
это очень большая
строка, многострочный
блок текста

Базовые операции
 Конкатенация (сложение)
>>>

>>> S1 = 'spam'
>>> S2 = 'eggs'
>>> print(S1 + S2)
'spameggs'

 Дублирование строки
>>>

>>> print('spam' * 3)
spamspamspam

 Длина строки (функция len)


>>>

>>> len('spam')
4

 Доступ по индексу
>>>

>>> S = 'spam'
>>> S[0]
's'
>>> S[2]
'a'
>>> S[-2]
'a'

Как видно из примера, в Python возможен и доступ по отрицательному


индексу, при этом отсчет идет от конца строки.
 Извлечение среза
Оператор извлечения среза: [X:Y]. X – начало среза, а Y – окончание;
символ с номером Y в срез не входит. По умолчанию первый индекс
равен 0, а второй - длине строки.
>>>

>>> s = 'spameggs'
>>> s[3:5]
'me'
>>> s[2:-2]
'ameg'
>>> s[:6]
'spameg'
>>> s[1:]
'pameggs'
>>> s[:]
'spameggs'

Кроме того, можно задать шаг, с которым нужно извлекать срез.


>>>

>>> s[::-1]
'sggemaps'
>>> s[3:5:-1]
''
>>> s[2::2]
'aeg'

Другие функции и методы строк


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

>>> s = 'spam'
>>> s[1] = 'b'
Traceback (most recent call last):
File "", line 1, in
s[1] = 'b'
TypeError: 'str' object does not support item assignment
>>> s = s[0] + 'b' + s[2:]
>>> s
'sbam'

Поэтому все строковые методы возвращают новую строку, которую


потом следует присвоить переменной.
Таблица "Функции и методы строк"
Функция или метод Назначение
S = 'str'; S = "str"; S =
Литералы строк
'''str'''; S = """str"""

S = "s\np\ta\nbbb" Экранированные последовательности

Неформатированные строки (подавляют


S = r"C:\temp\new"
экранирование)

S = b"byte" Строка байтов

S1 + S2 Конкатенация (сложение строк)

S1 * 3 Повторение строки

S[i] Обращение по индексу

S[i:j:step] Извлечение среза


Функция или метод Назначение
len(S) Длина строки

Поиск подстроки в строке. Возвращает номер


S.find(str, [start],[end])
первого вхождения или -1

Поиск подстроки в строке. Возвращает номер


S.rfind(str, [start],[end])
последнего вхождения или -1

Поиск подстроки в строке. Возвращает номер


S.index(str, [start],[end])
первого вхождения или вызывает ValueError

S.rindex(str, [start], Поиск подстроки в строке. Возвращает номер


[end]) последнего вхождения или вызывает ValueError

S.replace(шаблон,
Замена шаблона
замена)

S.split(символ) Разбиение строки по разделителю

S.isdigit() Состоит ли строка из цифр

S.isalpha() Состоит ли строка из букв

S.isalnum() Состоит ли строка из цифр или букв

S.islower() Состоит ли строка из символов в нижнем регистре

S.isupper() Состоит ли строка из символов в верхнем регистре

Состоит ли строка из неотображаемых символов


(пробел, символ перевода страницы ('\f'), "новая строка"
S.isspace()
('\n'), "перевод каретки" ('\r'), "горизонтальная
табуляция" ('\t') и "вертикальная табуляция" ('\v'))

S.istitle() Начинаются ли слова в строке с заглавной буквы

S.upper() Преобразование строки к верхнему регистру

S.lower() Преобразование строки к нижнему регистру


Функция или метод Назначение
S.startswith(str) Начинается ли строка S с шаблона str

S.endswith(str) Заканчивается ли строка S шаблоном str

S.join(список) Сборка строки из списка с разделителем S

ord(символ) Символ в его код ASCII

chr(число) Код ASCII в символ

Переводит первый символ строки в верхний регистр,


S.capitalize()
а все остальные в нижний

Возвращает отцентрованную строку, по краям


S.center(width, [fill])
которой стоит символ fill (пробел по умолчанию)

Возвращает количество непересекающихся


S.count(str, [start],[end]) вхождений подстроки в диапазоне [начало, конец] (0 и
длина строки по умолчанию)

Возвращает копию строки, в которой все символы


табуляции заменяются одним или несколькими
S.expandtabs([tabsize]) пробелами, в зависимости от текущего столбца. Если
TabSize не указан, размер табуляции полагается равным
8 пробелам

S.lstrip([chars]) Удаление пробельных символов в начале строки

S.rstrip([chars]) Удаление пробельных символов в конце строки

Удаление пробельных символов в начале и в конце


S.strip([chars])
строки

Возвращает кортеж, содержащий часть перед


первым шаблоном, сам шаблон, и часть после шаблона.
S.partition(шаблон)
Если шаблон не найден, возвращается кортеж,
содержащий саму строку, а затем две пустых строки
Функция или метод Назначение
Возвращает кортеж, содержащий часть перед
последним шаблоном, сам шаблон, и часть после
S.rpartition(sep)
шаблона. Если шаблон не найден, возвращается кортеж,
содержащий две пустых строки, а затем саму строку

Переводит символы нижнего регистра в верхний, а


S.swapcase()
верхнего – в нижний

Первую букву каждого слова переводит в верхний


S.title()
регистр, а все остальные в нижний

Делает длину строки не меньшей width, по


S.zfill(width)
необходимости заполняя первые символы нулями

Делает длину строки не меньшей width, по


S.ljust(width, fillchar="
необходимости заполняя последние символы символом
")
fillchar

Делает длину строки не меньшей width, по


S.rjust(width, fillchar="
необходимости заполняя первые символы символом
")
fillchar

S.format(*args,
Форматирование строки
**kwargs)

Что такое списки?


Списки в Python - упорядоченные изменяемые коллекции объектов
произвольных типов (почти как массив, но типы могут отличаться).
Чтобы использовать списки, их нужно создать. Создать список можно
несколькими способами. Например, можно обработать любой итерируемый
объект (например, строку) встроенной функцией list:

>>> list('список')
['с', 'п', 'и', 'с', 'о', 'к']

Список можно создать и при помощи литерала:

>>> s = [] # Пустой список


>>> l = ['s', 'p', ['isok'], 2]
>>> s
[]
>>> l
['s', 'p', ['isok'], 2]

Как видно из примера, список может содержать любое количество


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

>>> c = [c * 3 for c in 'list']


>>> c
['lll', 'iii', 'sss', 'ttt']

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

>>> c = [c * 3 for c in 'list' if c != 'i']


>>> c
['lll', 'sss', 'ttt']
>>> c = [c + d for c in 'list' if c != 'i' for d in 'spam' if d != 'a']
>>> c
['ls', 'lp', 'lm', 'ss', 'sp', 'sm', 'ts', 'tp', 'tm']

Но в сложных случаях лучше пользоваться обычным циклом for для


генерации списков.
Функции и методы списков
Создать создали, теперь нужно со списком что-то делать. Для списков
доступны основные встроенные функции, а также методы списков.
Таблица "методы списков"
Метод Что делает
list.append(x) Добавляет элемент в конец списка

Расширяет список list, добавляя в конец все элементы


list.extend(L)
списка L

list.insert(i, x) Вставляет на i-ый элемент значение x

Удаляет первый элемент в списке, имеющий значение


list.remove(x)
x. ValueError, если такого элемента не существует

Удаляет i-ый элемент и возвращает его. Если индекс не


list.pop([i])
указан, удаляется последний элемент

list.index(x, [start [, Возвращает положение первого элемента со значением


end]]) x (при этом поиск ведется от start до end)

list.count(x) Возвращает количество элементов со значением x

list.sort([key=функци
Сортирует список на основе функции
я])

list.reverse() Разворачивает список

list.copy() Поверхностная копия списка

list.clear() Очищает список


Нужно отметить, что методы списков, в отличие от строковых методов,
изменяют сам список, а потому результат выполнения не нужно записывать в
эту переменную.

>>> l = [1, 2, 3, 5, 7]
>>> l.sort()
>>> l
[1, 2, 3, 5, 7]
>>> l = l.sort()
>>> print(l)
None

И, напоследок, примеры работы со списками:

>>> a = [66.25, 333, 333, 1, 1234.5]


>>> print(a.count(333), a.count(66.25), a.count('x'))
210
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]

Модуль array. Массивы в python


Модуль array определяет массивы в python. Массивы очень похожи
на списки, но с ограничением на тип данных и размер каждого элемента.
Размер и тип элемента в массиве определяется при его создании и
может принимать следующие значения:
Код Минимальный
Тип в C Тип в python
типа размер в байтах
'b' signed char int 1

'B' unsigned char int 1

'h' signed short int 2

'H' unsigned short int 2

'i' signed int int 2

'I' unsigned int int 2

'l' signed long int 4

'L' unsigned long int 4

'q' signed long long int 8

unsigned long
'Q' int 8
long

'f' float float 4

'd' double float 8


Класс array.array(TypeCode [, инициализатор]) - новый массив,
элементы которого ограничены TypeCode, и инициализатор, который должен
быть списком, объектом, поддерживающий интерфейс буфера, или
итерируемый объект.
array.typecodes - строка, содержащая все возможные типы в массиве.
Массивы изменяемы. Массивы поддерживают все списковые методы
(индексация, срезы, умножения, итерации), и другие методы.
Методы массивов (array) в python
array.typecode - TypeCode символ, использованный при создании
массива.
array.itemsize - размер в байтах одного элемента в массиве.
array.append(х) - добавление элемента в конец массива.
array.buffer_info() - кортеж (ячейка памяти, длина). Полезно для
низкоуровневых операций.
array.byteswap() - изменить порядок следования байтов в каждом
элементе массива. Полезно при чтении данных из файла, написанного на
машине с другим порядком байтов.
array.count(х) - возвращает количество вхождений х в массив.
array.extend(iter) - добавление элементов из объекта в массив.
array.frombytes(b) - делает массив array из массива байт. Количество
байт должно быть кратно размеру одного элемента в массиве.
array.fromfile(F, N) - читает N элементов из файла и добавляет их в
конец массива. Файл должен быть открыт на бинарное чтение. Если доступно
меньше N элементов, генерируется исключение EOFError , но элементы,
которые были доступны, добавляются в массив.
array.fromlist(список) - добавление элементов из списка.
array.index(х) - номер первого вхождения x в массив.
array.insert(n, х) - включить новый пункт со значением х в массиве
перед номером n. Отрицательные значения рассматриваются относительно
конца массива.
array.pop(i) - удаляет i-ый элемент из массива и возвращает его. По
умолчанию удаляется последний элемент.
array.remove(х) - удалить первое вхождение х из массива.
array.reverse() - обратный порядок элементов в массиве.
array.tobytes() - преобразование к байтам.
array.tofile(f) - запись массива в открытый файл.
array.tolist() - преобразование массива в список.
Вот и всё, что можно было рассказать про массивы. Они используются
редко, когда нужно достичь высокой скорости работы. В остальных случаях
массивы можно заменить другими типами
данных: списками, кортежами, строками.
Зачем нужны кортежи, если есть списки?
 Защита от дурака. То есть кортеж защищен от изменений, как
намеренных (что плохо), так и случайных (что хорошо).
 Меньший размер. Дабы не быть голословным:
>>>

>>> a = (1, 2, 3, 4, 5, 6)
>>> b = [1, 2, 3, 4, 5, 6]
>>> a.__sizeof__()
36
>>> b.__sizeof__()
44

 Возможность использовать кортежи в качестве ключей словаря:


>>>

>>> d = {(1, 1, 1) : 1}
>>> d
{(1, 1, 1): 1}
>>> d = {[1, 1, 1] : 1}
Traceback (most recent call last):
File "", line 1, in
d = {[1, 1, 1] : 1}
TypeError: unhashable type: 'list'

Как работать с кортежами?


С преимуществами кортежей разобрались, теперь встает вопрос - а как
с ними работать. Примерно так же, как и со списками.
Создаем пустой кортеж:
>>>

>>> a = tuple() # С помощью встроенной функции tuple()


>>> a
()
>>> a = () # С помощью литерала кортежа
>>> a
()
>>>

Создаем кортеж из одного элемента:


>>>

>>> a = ('s')
>>> a
's'

Получилась строка. Как же нам получить кортеж?


>>>

>>> a = ('s', )
>>> a
('s',)

Все дело - в запятой. Сами по себе скобки ничего не значат, точнее,


значат то, что внутри них находится одна инструкция, которая может быть
отделена пробелами, переносом строк и прочим мусором. Кстати, кортеж
можно создать и так:
>>>

>>> a = 's',
>>> a
('s',)

Не увлекайтесь, и ставьте скобки, тем более, что бывают случаи, когда


скобки необходимы.
Ну и создать кортеж из итерируемого объекта можно с помощью все
той же пресловутой функции tuple()
>>>

>>> a = tuple('hello, world!')


>>> a
('h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!')

Операции с кортежами
Все операции над списками, не изменяющие список (сложение,
умножение на число, методы index() и count() и некоторые другие операции).
Можно также по-разному менять элементы местами и так далее.
Например, гордость программистов на python - поменять местами
значения двух переменных:

a, b = b, a

Что такое множество?


Множество в python - "контейнер", содержащий не повторяющиеся
элементы в случайном порядке.
Создаём множества:
>>>

>>> a = set()
>>> a
set()
>>> a = set('hello')
>>> a
{'h', 'o', 'l', 'e'}
>>> a = {'a', 'b', 'c', 'd'}
>>> a
{'b', 'c', 'a', 'd'}
>>> a = {i ** 2 for i in range(10)} # генератор множеств
>>> a
{0, 1, 4, 81, 64, 9, 16, 49, 25, 36}
>>> a = {} # А так нельзя!
>>> type(a)
<class 'dict'>

Как видно из примера, множества имеет тот же литерал, что и словарь,


но пустое множество с помощью литерала создать нельзя.
Множества удобно использовать для удаления повторяющихся
элементов:
>>>

>>> words = ['hello', 'daddy', 'hello', 'mum']


>>> set(words)
{'hello', 'daddy', 'mum'}

С множествами можно выполнять множество операций: находить


объединение, пересечение...
 len(s) - число элементов в множестве (размер множества).
 x in s - принадлежит ли x множеству s.
 set.isdisjoint(other) - истина, если set и other не имеют общих
элементов.
 set == other - все элементы set принадлежат other, все элементы
other принадлежат set.
 set.issubset(other) или set <= other - все элементы set принадлежат
other.
 set.issuperset(other) или set >= other - аналогично.
 set.union(other, ...) или set | other | ... - объединение нескольких
множеств.
 set.intersection(other, ...) или set & other & ... - пересечение.
 set.difference(other, ...) или set - other - ... - множество из всех
элементов set, не принадлежащие ни одному из other.
 set.symmetric_difference(other); set ^ other - множество из
элементов, встречающихся в одном множестве, но не встречающиеся в
обоих.
 set.copy() - копия множества.
И операции, непосредственно изменяющие множество:
 set.update(other, ...); set |= other | ... - объединение.
 set.intersection_update(other, ...); set &= other & ... - пересечение.
 set.difference_update(other, ...); set -= other | ... - вычитание.
 set.symmetric_difference_update(other); set ^= other - множество из
элементов, встречающихся в одном множестве, но не встречающиеся в
обоих.
 set.add(elem) - добавляет элемент в множество.
 set.remove(elem) - удаляет элемент из множества. KeyError, если
такого элемента не существует.
 set.discard(elem) - удаляет элемент, если он находится в множестве.
 set.pop() - удаляет первый элемент из множества. Так как множества
не упорядочены, нельзя точно сказать, какой элемент будет первым.
 set.clear() - очистка множества.
frozenset
Единственное отличие set от frozenset заключается в том, что set -
изменяемый тип данных, а frozenset - нет. Примерно похожая ситуация
с списками и кортежами.
>>>

>>> a = set('qwerty')
>>> b = frozenset('qwerty')
>>> a == b
True
>>> True
True
>>> type(a - b)
<class 'set'>
>>> type(a | b)
<class 'set'>
>>> a.add(1)
>>> b.add(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'

Справка по использованию генератора случайных чисел.


import random
random.random() — возвращает псевдослучайное число от 0.0 до 1.0
random.random()
0.07500815468466127

random.seed
random.seed(<Параметр>) — настраивает генератор случайных чисел
на новую последовательность. По умолчанию используется системное время.
random.seed(20)
random.random()
0.9056396761745207
random.random()
0.6862541570267026
random.seed(20)
random.random()
0.9056396761745207

random.uniform
random.uniform(<Начало>, <Конец>) — возвращает псевдослучайное
вещественное число в диапазоне от <Начало> до <Конец>:
random.uniform(0, 20)
15.330185127252884
random.uniform(0, 20)
18.092324756265473

random.randint
random.randint(<Начало>, <Конец>) — возвращает псевдослучайное
целое число в диапазоне от <Начало> до <Конец>:
random.randint(1,27)
9
random.randint(1,27)
22
Задание.
Задание 1. Дана строка, заканчивающаяся точкой.
a. Вывести длину строки.
b. Подсчитать, сколько слов в строке.
c. Найти длину самого короткого слова и самого длинного слова.
d. Преобразовать ее, удалив каждый символ * и повторив каждый
символ, отличный от *.
Задание 2. Варианты заданий на перемещение элементов списка.
Элементы списка вводить с помощью random.
1. Скорректировать список A=(a1, а2, ..., аn), переписав в начало списка
группу, содержащую наибольшее число подряд идущих положительных
элементов.
2. В списке A=(a1, а2, ..., аn) все элементы, равные нулю, поставить
сразу после максимального элемента данного списка.
3. В списке A=(a1, а2, ..., аn) все отрицательные элементы отправить в
«хвост» списка.
4. В списке A=(a1, а2, ..., аn) все положительные элементы, стоящие
перед минимальным положительным элементом, переслать в «хвост» списка.
5. В списке A=(a1, а2, ..., аn) все положительные элементы, начиная со
второго положительного, отправить в хвост списка.
6. В одномерном списке A=(a1, а2, ..., аn) группу элементов,
содержащую наибольшее число подряд идущих отрицательных элементов,
переписать в «хвост» списка.
7. В одномерном списке A=(a1, а2, ..., аn) все отрицательные элементы,
имеющие нечетный порядковый номер, отправить в «хвост» списка, т.  е.
поместить на место последних элементов.
8. В одномерном списке A=(a1, а2, ..., аn) все положительные элементы,
имеющие четный порядковый номер, переписать в начало списка.
9. В одномерном списке A=(a1, а2, ..., аn) отрицательные элементы,
имеющие четный порядковый номер, переписать в начало списка.
10.В одномерном списке A=(a1, а2, ..., аn) группу, содержащую
наибольшее число подряд идущих положительных элементов, переписать в
хвост списка.
Задание 3. Варианты заданий на удаление элементов списка.
1. В списке A=(a1, а2, ..., аn) удалить последнюю группу
положительных элементов. Группой называется подряд идущие элементы
одного знака, число которых больше или равно 2.
2. В списке A=(a1, а2, ..., аn) удалить все подряд идущие отрицательные
элементы, идущие вслед за минимальным элементом списка.
3. В списке A=(a1, а2, ..., аn) удалить все отрицательные элементы,
стоящие перед минимальным элементом списка.
4. В списке A=(a1, а2, ..., аn) удалить все элементы, меньшие, чем
элемент списка, расположенный слева от максимального.
5. В списке A=(a1, а2, ..., аn) удалить все элементы, стоящие между
минимальным положительным и максимальным отрицательным элементами.
6. В списке A=(a1, а2, ..., аn) удалить все положительные элементы,
имеющие четный порядковый номер, идущие после минимального элемента
списка.
7. В одномерном списке A=(a1, а2, ..., аn) удалить все отрицательные
элементы, расположенные между положительными.
8. В одномерном списке A=(a1, а2, ..., аn) удалить все равные элементы,
оставив только один из данных групп равных.
9. В одномерном списке A=(a1, а2, ..., аn) удалить все цепочки
отрицательных элементов, расположенные между положительными.
10.В списке A=(a1, а2, ..., аn) удалить все элементы, стоящие между
минимальным положительным и максимальным отрицательным элементами.
Задание 4.
Решето Эратосфена — алгоритм нахождения всех простых чисел до
некоторого целого числа n, который приписывают древнегреческому
математику Эратосфену Киренскому. Как и во многих случаях, здесь
название алгоритма говорит о принципе его работы, то есть решето
подразумевает фильтрацию, в данном случае фильтрацию всех чисел за
исключением простых. По мере прохождения списка нужные числа
остаются, а ненужные (они называются составными) исключаются.
Для нахождения всех простых чисел не больше заданного числа n,
следуя методу Эратосфена, нужно выполнить следующие шаги:
1. Выписать подряд все целые числа от двух до n (2, 3, 4, …, n).
2. Пусть переменная p изначально равна двум — первому простому
числу.
3. Зачеркнуть в списке числа от 2p до n считая шагами по p (это будут
числа кратные p: 2p, 3p, 4p, …).
4. Найти первое незачёркнутое число в списке, большее чем p, и
присвоить значению переменной p это число.
5. Повторять шаги 3 и 4, пока возможно.
Теперь все незачёркнутые числа в списке — это все простые числа от 2
до n.
Требуется:
а) вычислить все числа от 1 до n, кратные 7;
б) вычислить все простые числа от 1 до n;
в) определить простые числа от 1 до n, кратные 7.
Для выполнения задания следует использовать списки и множества.
Практическая работа №4. Рекурсивные функции и работа с файлами.

Функции
Именные функции, инструкция def
Функция в python - объект, принимающий аргументы и возвращающий
значение. Обычно функция определяется с помощью инструкции def.
Определим простейшую функцию:
def add(x, y):
return x + y
Инструкция return говорит, что нужно вернуть значение. В нашем
случае функция возвращает сумму x и y.
Теперь мы ее можем вызвать:
>>> add(1, 10)
11
>>> add('abc', 'def')
'abcdef'
Функция может быть любой сложности и возвращать любые объекты
(списки, кортежи, и даже функции!):
>>> def newfunc(n):
... def myfunc(x):
... return x + n
... return myfunc
...
>>> new = newfunc(100) # new - это функция
>>> new(200)
300
Функция может и не заканчиваться инструкцией return, при этом
функция вернет значениеNone:
>>> def func():
... pass
...
>>> print(func())
None

Аргументы функции
Функция может принимать произвольное количество аргументов или
не принимать их вовсе. Также распространены функции с произвольным
числом аргументов, функции с позиционными и именованными
аргументами, обязательными и необязательными.
>>> def func(a, b, c=2): # c - необязательный аргумент
... return a + b + c
...
>>> func(1, 2) # a = 1, b = 2, c = 2 (по умолчанию)
5
>>> func(1, 2, 3) # a = 1, b = 2, c = 3
6
>>> func(a=1, b=3) # a = 1, b = 3, c = 2
6
>>> func(a=3, c=6) # a = 3, c = 6, b не определен
Traceback (most recent call last):
File "", line 1, in
func(a=3, c=6)
TypeError: func() takes at least 2 arguments (2 given)
Функция также может принимать переменное количество позиционных
аргументов, тогда перед именем ставится *:
>>> def func(*args):
... return args
...
>>> func(1, 2, 3, 'abc')
(1, 2, 3, 'abc')
>>> func()
()
>>> func(1)
(1,)
Как видно из примера, args - это кортежиз всех переданных аргументов
функции, и с переменной можно работать также, как и с кортежем.
Функция может принимать и произвольное число именованных
аргументов, тогда перед именем ставится **:
>>> def func(**kwargs):
... return kwargs
...
>>> func(a=1, b=2, c=3)
{'a': 1, 'c': 3, 'b': 2}
>>> func()
{}
>>> func(a='python')
{'a': 'python'}
В переменной kwargs у нас хранится словарь, с которым мы, опять-
таки, можем делать все, что нам заблагорассудится.

Анонимные функции, инструкция lambda


Анонимные функции могут содержать лишь одно выражение, но и
выполняются они быстрее. Анонимные функции создаются с помощью
инструкции lambda. Кроме этого, их не обязательно присваивать переменной,
как делали мы инструкцией def func():
>>> func = lambda x, y: x + y
>>> func(1, 2)
3
>>> func('a', 'b')
'ab'
>>> (lambda x, y: x + y)(1, 2)
3
>>> (lambda x, y: x + y)('a', 'b')
'ab'
lambda функции, в отличие от обычной, не требуется инструкция
return, а в остальном, ведет себя точно так же:
>>> func = lambda *args: args
>>> func(1, 2, 3, 4)
(1, 2, 3, 4)
Понятие рекурсии, реализация в языке Python
В программировании рекурсия — вызов функции (процедуры) из неё
же самой, непосредственно (простая рекурсия) или через другие функции
(сложная или косвенная рекурсия), например, функция  вызывает функцию
, а функция — функцию . Количество вложенных вызовов функции или
процедуры называется глубиной рекурсии.
 Проще сказать нельзя. Про рекурсии есть известная поговорка:
Чтобы понять рекурсию, нужно сперва понять рекурсию
Итак, питон позволяет работать с рекурсиями легко и непринужденно.
Самый первый пример рекурсии, с которой сталкиваются большинство
программистов - это нахождение факториала. Код может быть таким:
def factorial(n):
if n <= 1: return 1
else: return n * factorial(n - 1)
Как видно, мы записали инструкцию if else слегка необычным для
питона способом, но это позволяется в данном случаее, ввиду того, что
читабельность здесь не ухудшается, но не следует злоупотреблять таким
стилем. И вообще, PEP8всех рассудит. :)
Теперь проясним несколько важных особенностей, о которых всегда
нужно помнить при работе с рекурсиями.
1. Существует ограничение на глубину рекурсии. По умолчанию
оно равно 1000.
2. Для того, чтобы изменить это ограничение нужно вызвать
функцию sys.setrecursionlimit(), а для просмотра текущего
лимита sys.getrecursionlimit().
3. Не смотря на это - существует ограничение размером стека,
который устанавливается операционной системой.
4. Рекурсия в Python не может использоваться в функциях-
генераторах и сопрограммах. Однако, можно это поведение исправить, но
лучше не стоит.
5. И последнее - применение декораторов к рекурсивным функциям
может приводить к неожиданным результатам, поэтому будьте очень
осторожны декорируя рекурсивные функции.
Также, всегда следует определять точки выхода из рекурсивных
функций. Это как с циклами - бесконечный цикл может здорово «просадить»
вашу операционную систему. И наконец, где лучше применять рекурсию, а
где лучше воздержаться и обойтись, например циклами. Конечно, здесь
многое зависит от задачи, но всегда следует помнить, что рекурсия в разы
медленнее цикла. Так уж устроен питон, что вызов функции дорого вам
обходится :) Вообще, в циклах не стоит вызывать функции, а уж рекурсивные
функции и подавно.
Рекурсия хорошо подходит там, где производительность не слишком
важна, а важнее читабельность и поддержка кода. К примеру, напишите две
функции для обхода дерева каталогов, одну рекурсивную, другую с циклами.
Работа с файлами.
Прежде, чем работать с файлом, его надо открыть. С этим замечательно
справится встроенная функция open:

f = open('text.txt', 'r')
У функции open много параметров, они указаны в статье "Встроенные
функции", нам пока важны 3 аргумента: первый, это имя файла. Путь к файлу может
быть относительным или абсолютным. Второй аргумент, это режим, в котором мы будем
открывать файл.

Режим Обозначение

'r' открытие на чтение (является значением по умолчанию).

открытие на запись, содержимое файла удаляется, если файла не


'w'
существует, создается новый.

'x' открытие на запись, если файла не существует, иначе исключение.

'a' открытие на дозапись, информация добавляется в конец файла.

'b' открытие в двоичном режиме.

't' открытие в текстовом режиме (является значением по умолчанию).

'+' открытие на чтение и запись


Режимы могут быть объединены, то есть, к примеру, 'rb' - чтение в
двоичном режиме. По умолчанию режим равен 'rt'.
И последний аргумент, encoding, нужен только в текстовом режиме
чтения файла. Этот аргумент задает кодировку.

Чтение из файла
Открыли мы файл, а теперь мы хотим прочитать из него информацию.
Для этого есть несколько способов, но большого интереса заслуживают лишь
два из них.
Первый - метод read, читающий весь файл целиком, если был вызван
без аргументов, и n символов, если был вызван с аргументом (целым числом
n).
>>>

>>> f = open('text.txt')
>>> f.read(1)
'H'
>>> f.read()
'ello world!\nThe end.\n\n'

Ещё один способ сделать это - прочитать файл построчно,


воспользовавшись циклом for:
>>>

>>> f = open('text.txt')
>>> for line in f:
... line
...
'Hello world!\n'
'\n'
'The end.\n'
'\n'

Запись в файл
Теперь рассмотрим запись в файл. Попробуем записать в файл вот
такой вот список:
>>>

>>> l = [str(i)+str(i-1) for i in range(20)]


>>> l
['0-1', '10', '21', '32', '43', '54', '65', '76', '87', '98', '109', '1110', '1211', '1312',
'1413', '1514', '1615', '1716', '1817', '1918']

Откроем файл на запись:


>>>

>>> f = open('text.txt', 'w')

Запись в файл осуществляется с помощью метода write:


>>>

>>> for index in l:


... f.write(index + '\n')
...
4
3
3
3
3

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

>>> f.close()

Теперь попробуем воссоздать этот список из получившегося файла.


Откроем файл на чтение (надеюсь, вы поняли, как это сделать?), и прочитаем
строки.
>>>

>>> f = open('text.txt', 'r')


>>> l = [line.strip() for line in f]
>>> l
['0-1', '10', '21', '32', '43', '54', '65', '76', '87', '98', '109', '1110', '1211', '1312',
'1413', '1514', '1615', '1716', '1817', '1918']
>>> f.close()
Задание.
Задание 1. Создайте текстовый файл in.txt, в который поместите текст
(объёмом примерно 0,5 страницы). Затем ваша программа должна считать
данные из файла, выполнить операции в соответствии с вариантом. Результат
нужно записать в текстовый файл out.txt.
Задание 2. Выполните задание в соответствии с вашим вариантом.
Практическая работа №5. Многопоточность в Python
С появлением многоядерных процессоров стала общеупотребительной
практика распространять нагрузку на все доступные ядра. Существует два
основных подхода в распределении нагрузки: использование процессов и
потоков.
Использование нескольких процессов фактически означает
использование нескольких программ, которые выполняются независимо друг
от друга. Программно это решается с помощью системных вызовов exec и
fork. Такой подход создает большие неудобства в управлении обмена
данными между этими программами.
В качестве альтернативы существует другой подход – создание
многопоточных программ. Обмен данными между потоками существенно
упрощается. Но управление такими программами усложняется, и вся
ответственность ложится на программиста.
1. Как работают процессы
В питоне есть стандартный модуль subprocess, который упрощает
управление другими программами, передавая им опции командной строки и
организуя обмен данными через каналы (pipe). Мы рассмотрим пример, в
котором пользователь запускает программу из командной строки, которая в
свою очередь запустит несколько дочерних программ. В данном примере два
скрипта – рarent.py и child.py. Запускается parent.py. Child.py выступает в
роли аргумента command, который передается в запускаемый процесс. У
этого процесса есть стандартный вход, куда мы передаем два аргумента –
поисковое слово и имя файла. Мы запустим два экземпляра программы
child.py, каждый экземпляр будет искать слово word в своем файле – это
будут файлы исходников самих программ. Запись на стандартный вход
осуществляет модуль subprocess. Каждый процесс пишет результат своего
поиска в консоль. В главном процессе мы ждем, пока все child не закончат
свою работу.
Код parent.py:
import os
import subprocess
import sys
 
 
child = os.path.join(os.path.dirname(__file__), "./child.py")
word  = 'word'
file = ['./parent.py','./child.py']
 
pipes = []
0 for i in range(0,2):
  command = [sys.executable, child]
1   pipe = subprocess.Popen(command, stdin=subprocess.PIPE)
  pipes.append(pipe)
2   pipe.stdin.write(word.encode("utf8") + b"\n")
  pipe.stdin.write(file[i].encode("utf8") + b"\n")
3   pipe.stdin.close()
 
4 while pipes:
    pipe = pipes.pop()
5     pipe.wait()
6

1
Код child.py:
import sys
 
word = sys.stdin.readline().rstrip()
filename = sys.stdin.readline().rstrip()
 
try:
  with open(filename, "rb") as fh:
    while True:
      current = fh.readline()
      if not current:
0           break
      if (word in current ):
1           print("find: {0} {1}".format(filename,word))
except :
2     pass

3
4

5
2. Как работают потоки в питоне
Если нужно, чтобы ваше приложение выполняло несколько задач в
одно и то же время, то можете воспользоваться потоками (threads). Потоки
позволяют приложениям выполнять в одно и то же время множество задач.
Многопоточность (multi-threading) важна во множестве приложений, от
примитивных серверов до современных сложных и ресурсоёмких игр.
Когда в одной программе работают несколько потоков, возникает
проблема разграничения доступа потоков к общим данным. Предположим,
что есть два потока, имеющих доступ к общему списку. Первый поток может
делать итерацию по этому списку:
for x in L
а второй в этот момент начнет удалять значения из этого списка. Тут
может произойти все что угодно: программа может упасть, или мы просто
получим неверные данные.
Решением в этом случае является применение блокировки. При этом
доступ к заблокированному списку будет иметь только один поток, второй
будет ждать, пока блокировка не будет снята.
Применение блокировки порождает другую проблему – дедлок
(deadlock) – мертвая блокировка. Пример дедлока: имеется два потока и два
списка. Первый поток блокирует первый список, второй поток блокирует
второй список. Первый поток изнутри первой блокировки пытается получить
доступ к уже заблокированному второму списку, второй поток пытается
проделать то же самое с первым списком. Получается неопределенная
ситуация с бесконечным ожиданием. Эту ситуации легко описать, на
практике все гораздо сложнее.
Вариантом решения проблемы дедлоков является политика
определения очередности блокировок. Например, в предыдущем примере мы
должны определить, что блокировка первого списка идет всегда первой, а
уже потом идет блокировка второго списка.
Другая проблема с блокировками – в том, что несколько потоков могут
одновременно ждать доступа к уже заблокированному ресурсу и при этом
ничего не делать. Каждая питоновская программа всегда имеет главный
управляющий поток.
Питоновская реализация многопоточности ограниченная.
Интерпретатор питона использует внутренний глобальный блокировщик
(GIL), который позволяет выполняться только одному потоку. Это сводит на
нет преимущества многоядерной архитектуры процессоров. Для
многопоточных приложений, которые работают в основном на дисковые
операции чтения/записи, это не имеет особого значения, а для приложений,
которые делят процессорное время между потоками, это является серьезным
ограничением.
3. Создание потока
Для создания потоков мы будем использовать стандартный модуль
threading. Есть два варианта создания потоков:
вызов функции
threading.Thread()
вызов класса
threading.Thread
Следующий пример показывает, как к потоку приаттачить функцию
через вызов функции:
import threading
import time
def clock(interval):
    while True:
        print("The time is %s" % time.ctime())
        time.sleep(interval)
t = threading.Thread(target=clock, args=(15,))
t.daemon = True
t.start()
Пример на создание потока через вызов класса: в конструкторе
обязательно нужно вызвать конструктор базового класса. Для запуска потока
нужно выполнить метод start() объекта-потока, что приведет к выполнению
действий в методе run():

import threading
import time
class ClockThread(threading.Thread):
    def __init__(self,interval):
        threading.Thread.__init__(self)
        self.daemon = True
        self.interval = interval
    def run(self):
0         while True:
            print("The time is %s" % time.ctime())
1             time.sleep(self.interval)
t = ClockThread(15)
2 t.start()

3
Для управления потоками существуют методы:
start() – дает потоку жизнь.
run() –этот метод представляет действия, которые должны быть
выполнены в потоке.
join([timeout]) – поток, который вызывает этот метод,
приостанавливается, ожидая завершения потока, чей метод вызван.
Параметр timeout (число с плавающей точкой) позволяет указать время
ожидания (в секундах), по истечении которого приостановленный поток
продолжает свою работу независимо от завершения потока, чей
метод join был вызван. Вызывать join()некоторого потока можно много раз.
Поток не может вызвать метод join() самого себя. Также нельзя ожидать
завершения еще не запущенного потока.
getName() – возвращает имя потока.
setName(name) – присваивает потоку имя name.
isAlive() – возвращает истину, если поток работает (метод run() уже
вызван).
isDaemon() – возвращает истину, если поток имеет признак демона.
setDaemon(daemonic) – устанавливает признак daemonic того, что поток
является демоном.
activeCount() – возвращает количество активных в настоящий момент
экземпляров класса Thread. Фактически это len(threading.enumerate()).
currentThread() – возвращает текущий объект-поток, т.е.
соответствующий потоку управления, который вызвал эту функцию.
enumerate() – возвращает список активных потоков.

Задание
Главный поток программы должен генерировать строки случайного
содержания и помещать их в конец списка. Дочерний поток №1 должен
выдавать текущее состояние списка на экран. Дочерний поток №2
пробуждается каждые пять секунд и сортирует список в лексикографическом
порядке и сохраняет в файл.

Практическая работа №6 – ООП в python


Объектно-ориентированная парадигма имеет несколько принципов:
 Данные структурируются в виде объектов, каждый из которых
имеет определенный тип, то есть принадлежит к какому-либо классу.
 Классы – результат формализации решаемой задачи, выделения
главных ее аспектов.
 Внутри объекта инкапсулируется логика работы с относящейся к
нему информацией.
 Объекты в программе взаимодействуют друг с другом,
обмениваются запросами и ответами.
 При этом объекты одного типа сходным образом отвечают на одни
и те же запросы.
 Объекты могут организовываться с более сложные структуры,
например, включать другие объекты или наследовать от одного или
нескольких объектов.
Класс — тип, описывающий устройство объектов. Объект — это
экземпляр класса. Класс можно сравнить с чертежом, по которому создаются
объекты.
Python соответствует принципам объектно-ориентированного
программирования. В python всё является объектами - и строки, и списки, и
словари, и всё остальное.
Но возможности ООП в python этим не ограничены. Программист
может написать свой тип данных (класс), определить в нём свои методы.
Это не является обязательным - мы можем пользоваться только
встроенными объектами. Однако ООП полезно при долгосрочной разработке
программы несколькими людьми, так как упрощает понимание кода.
Приступим теперь собственно к написанию своих классов на python.
Попробуем определить собственный класс:
>>>
>>> # Пример простейшего класса, который ничего не делает
... class A:
... pass
Теперь мы можем создать несколько экземпляров этого класса:
>>>
>>> a = A()
>>> b = A()
>>> a.arg = 1 # у экземпляра a появился атрибут arg, равный 1
>>> b.arg = 2 # а у экземпляра b - атрибут arg, равный 2
>>> print(a.arg)
1
>>> print(b.arg)
2
>>> c = A()
>>> print(c.arg) # а у этого экземпляра нет arg
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'arg'
Классу возможно задать собственные методы:
>>>
>>> class A:
... def g(self): # self - обязательный аргумент, содержащий в себе
экземпляр
... # класса, передающийся при вызове метода,
... # поэтому этот аргумент должен присутствовать
... # во всех методах класса.
... return 'hello world'
...
>>> a = A()
>>> a.g()
'hello world'
Предположим, что существует набор строковых переменных для
описания адреса проживания некоторого человека:
addr name = 'Ivan Ivanov' # имя человека
addr linel = '1122 Main Street'
addr line2 = ''
addr city = 'Panama City Beach'
addr state = 'FL'
addr zip = '32407' # индекс
Напишем функцию, которая выводит на экран всю информацию о
человеке:
def printAddress(name, line1, line2, city, state, zip_code):
print(name)
if len(line1) > 0:
print(line1)
if len(line2) > 0:
print(line2)
print(city + ", " + state + " " + zip_code)

Вызов функции, передача аргументов:


printAddress(addr_name, addr_line1, addr_line2, addr_city, addr_state,
addr_zip)

В результате работы программы:


>>>
======== RESTART: C:/Python35-32/addr.py ========
Ivan Ivanov
1122 Main Street
Panama City Beach, FL 32407
>>>
Предположим, что изменились начальные условия и у человека в
адресе появился второй индекс. Создадим новую переменную:
#добавим переменную, содержащую индекс
addr_zip2 = "678900"
Изменим функцию printAddress с учетом новых сведений:
def printAddress(name, linel, line2, city, state, zip_code, zip2):
#добавили параметр zip2
print(name)
if len(line1) > 0:
print(line1)
if len(line2) > 0:
print(line2)
#добавили вывод на экран переменной zip2
print(city + ", " + state + " " + zip_code + zip2)
#добавили новый аргумент addr_zip2:
printAddress (addr_name, addr_line1, addr_line2, addr_city,
addr_state, addr_zip, addr_zip2)
Пришлось несколько раз добавить новый индекс, чтобы функция
printAddress корректно отработала при новых условиях. Какой недостаток у
рассмотренного подхода? Огромное количество переменных. Чем больше
сведений о человеке хотим обработать, тем больше переменных мы должны
создать. Конечно, можно поместить всё в список (элементами списка тогда
будут строки), но в Python есть более универсальный подход для работы с
наборами разнородных данных, ориентированный на объекты.
Создадим структуру данных (класс) с именем Address, которая будет
содержать все сведения об адресе человека:
class Address: # имя класса выбирает программист
name = "" # поля класса
line1 = ""
line2 = ""
city = ""
state = ""
zip_code = ""
Класс задает шаблон для хранения адреса. Превратить шаблон в
конкретный адрес можно через создание объекта (экземпляра)43 класса
Address44:
homeAddress = Address()
Теперь можем заполнить поля объекта конкретными значениями:
#заполняем поле name объекта
homeAddress: homeAddress.name = "Ivan Ivanov"
homeAddress.line1 = "701 N. C Street"
homeAddress.line2 = "Carver Science Building"
homeAddress.city = "Indianola"
homeAddress.state = "IA"
homeAddress.zip code = "50125"
Создадим еще один объект класса Address, который содержит
информацию о загородном доме того же человека:
#переменная содержит адрес объекта класса Address:
vacationHomeAddress = Address()
Зададим поля объекта, адрес которого находится в переменной
vacationHomeAddress:
vacationHomeAddress.name = "Ivan Ivanov"
vacationHomeAddress.linel = "1122 Main Street"
vacationHomeAddress.line2 = ""
vacationHomeAddress.city = "Panama City Beach"
vacationHomeAddress.state = "FL"
vacationHomeAddress.zip code = "32407"
Выведем на экран информацию о городе для основного и загородного
адресов проживания (через указание имен объектов):
print("Основной адрес проживания " + homeAddress.city)
print("Адрес загородного дома " + vacationHomeAddress.city)
Изменим исходный текст функции printAddress с учетом полученных
знаний об объектах:
def printAddress(address): # передаем в функцию объект
print(address.name) # выводим на экран поле объекта
if len(address.line1) > 0:
print(address.line1)
if len(address.line2) > 0:
print(address.line2)
print(address.city + ", " + address.state + " " + address.zip code)
Если объекты homeAddress и vacationHomeAddress ранее были
созданы, то можем вывести информацию о них, передав в качестве аргумента
функции printAddress:
printAddress(homeAddress)
printAddress(vacationHomeAddress)
В результате выполнения программы получим:
>>>
========= RESTART: C:/Python35-32/addr2.py ==========
Ivan Ivanov
701 N. C Street
Carver Science Building
Indianola, IA 50125
Ivan Ivanov
1122 Main Street
Panama City Beach, FL 32407
>>>
Возможности классов и объектов не ограничиваются лишь
объединением переменных под одним именем, т.е. хранением состояния
объекта. Классы также позволяют задавать функции внутри себя (методы)
для работы с полями класса, т.е. влиять на поведение объекта.
Создадим класс Dog:
class Dog:
age = 0 # возраст собаки
name = "" # имя собаки
weight = 0 # вес собаки
# Первым аргументом любого метода всегда является self, т.е. сам
объект
def bark(self): # функция внутри класса называется методом
# self.name - обращение к имени текущего объекта-собаки
print(self.name, " говорит гав")
#Создадим объект myDog класса Dog: myDog = Dog()
#Присвоим значения полям объекта myDog:
myDog.name = "Spot" # Придумываем имя созданной собаке
myDog.weight = 20 # Указываем вес собаки
myDog.age = 1 # Возраст собаки
#Вызовем метод bark объекта myDog, т.е. попросим собаку подать
голос:
myDog.bark()
#Полная форма для вызова метода myDog.bark() будет:
Dog.bark(myDog),
#т.е. полная форма требует в качестве первого аргумента сам объект -
self

Результат работы программы:


========== RESTART: C:/Python35-32/ndog.py ========
Spot говорит гав
>>>

Данный пример демонстрирует объектно-ориентированный подход в


программировании, когда создаются объекты, приближенные к реальной
жизни. Между объектами происходит взаимодействие посредством вызова
методов. Поля объекта (переменные) фиксируют его состояние, а вызов
метода приводит к реакции объекта и/или изменению его состояния
(изменению переменных внутри объекта).

Упражнение 1
Создайте класс Cat. Определите атрибуты name (имя), color (цвет) и
weight (вес). Добавьте метод под названием meow («мяуканье»). Создайте
объект класса Cat, установите атрибуты, вызовите метод meow.
В предыдущем примере между созданием объекта myDog класса Dog и
присвоению ему имени (myDog.name="Spot") прошло некоторое время.
Может случиться так, что программист забудет указать имя и тогда собака
будет безымянная - такого допустить мы не можем! Избежать подобной
ошибки позволяет специальный метод (конструктор), который вызывается
сразу в момент создания объекта заданного класса.
Сначала рассмотрим работу конструктора в общем виде:
class Dog:
name = ""
#Конструктор вызывается в момент создания объекта этого типа;
#специальный метод Python, поэтому два нижних подчеркивания
def __init__(self):
print("Родилась новая собака!")
#создаем собаку (объект myDog класса Dog)
myDog = Dog()

Запустим программу:
>>>
========== RESTART: C:/Python35-32/dog1.py ==========
Родилась новая собака!
>>>
Рассмотрим пример присвоения имени собаки через вызов
конструктора класса:
class Dog ():
name = ""
#Конструктор
#Вызывается на момент создания объекта этого типа
init (self, newName):
self.name = newName

#Создаем собаку и устанавливаем ее имя:


myDog = Dog("Spot")
#Вывести имя собаки, убедиться, что оно было установлено
print(myDog.name)
#Следующая команда выдаст ошибку, потому что
# конструктору не было передано имя:
#herDog = Dog()

Результат работы программы:


>>>
========= RESTART: C:/Python35-32/dog2.py =========
Spot
>>>

Теперь имя собаки присваивается в момент ее создания. В


конструкторе указали self.name, т.к. в момент вызова конструктора вместо
self подставится конкретный объект, т.е. myDog.
В предыдущем примере для обращения к имени собаки мы выводили
на экран поле myDog.name, т.е., переводя на язык реального мира, мы
залезали во внутренности объекта и доставали оттуда информацию. Звучит
жутковато, поэтому обеспечим «гуманные» методы для работы с именем
объекта-собаки (setName и getName):
class Dog:
name = ""
# Конструктор вызывается в момент создания объекта этого класса
init (self, newName):
self.name = newName

# Можем в любой момент вызвать метод и изменить имя собаки


def setName(self, newName):
self.name = newName
# Можем в любой момент вызвать метод и узнать имя собаки
def getName(self):
return self.name # возвращаем текущее имя объекта
# Создаем собаку с начальным именем:
myDog = Dog("Spot")
# Выводим имя собаки:
print(myDog.getName())
# Установим новое имя собаки:
myDog.setName("Sharik")
# Посмотрим изменения имени:
print(myDog.getName())

Проверим, что все работает:

>>>

========== RESTART: C:/Python35-32/dog3.py ===========


Spot
Sharik
>>>

Упражнение 2
1. Напишите код, описывающий класс Animal:
• добавьте атрибут имени животного;
• добавьте метод eat, выводящий «Ням-ням»;
• добавьте методы getName и setName;
• добавьте метод makeNoise, выводящий «Имя животного говорит
Гррр»;
• добавьте конструктор классу Animal, выводящий «Родилось
животное имя животного».
2. Основная программа:
• создайте животное, в момент создания определите его имя;
• узнайте имя животного через вызов метода getName;
• измените имя животного через вызов метода setName;
• вызовите eat и makeNoise для животного.

Упражнение 3
Создайте класс StringVar для работы со строковым типом данных,
содержащий методы set и get. Метод set служит для изменения содержимого
строки, get - для получения содержимого строки. Создайте объект типа
StringVar и протестируйте его методы.

Упражнение 4
Создайте класс точка Point, позволяющий работать с координатами (x,
y). Добавьте необходимые методы класса.

Упражнение 5
1. Напишите код, описывающий класс Animal:
Добавьте атрибут имени животного.
Добавьте метод eat, выводящий «Ням-ням».
Добавьте методы getName и setName.
Добавьте метод makeNoise, выводящий «Имя животного говорит
Гррр».
Добавьте конструктор класса Animal, выводящий «Родилось
животное».
2. Пусть Animal будет родительским для класса Cat. Метод makeNoise
класса Cat выводит «Имя животного говорит Мяу». Конструктор класса Cat
выводит «Родился кот», а также вызывает родительский конструктор.
3. Пусть Animal будет родительским для класса Dog. Метод makeNoise
для Dog выводит «Имя животного говорит Гав». Конструктор Dog выводит
«Родилась собака», а также вызывает родительский конструктор.
4. Основная программа. Код, создающий кота, двух собак и одно
простое животное. Дайте имя каждому животному (через вызов методов).
Код, вызывающий eat и makeNoise для каждого животного.
Практическая работа №7 – Работа с pyQT

PyQt5 - это набор Python библиотек для создания графического


интерфейса на базе платформы Qt5 от компании Digia.
Он доступен для Python 2.x и 3.x. 
Библиотека Qt является одной из самых мощных библиотек GUI
(графического интерфейса пользователя).
Установить PyQt5 на Windows можно с официального
сайта библиотеки.
PyQt5 реализован в виде набора python-модулей. Эта библиотека имеет
более 620 классов и 6000 функций и методов.
Это мультиплатформенная библиотека, которая работает на всех
основных операционных системах, в том числе Unix, Windows и Mac OS.
Классы PyQt5 разделены на несколько модулей, включая следующие:
QtCore, QtGui, QtWidgets, QtMultimedia, QtBluetooth, QtNetwork,
QtPositioning, Enginio, QtWebSockets, QtWebKit, QtWebKitWidgets, QtXml,
QtSvg, QtSql, QtTest.

Особенности модулей:
- Модуль QtCore содержит ядро с неграфической функциональностью.
Этот модуль используется для работы с временем, файлами, папками,
различными типами файлов, потоками, адресами URL, MIME-типами и
процессами.
- QtGui содержит классы для интеграции систем окон, обработки
событий, 2D-графики, базовой обработки изображений, шрифтов и текста.
- Модуль QtWidgets содержит классы, которые обеспечивают набор UI-
элементов для создания классических пользовательских интерфейсов.
- QtMultimedia содержит классы для управления мультимедиа-
содержимым, а также API для доступа к камере или функциональности
радио.
- Модуль QtBluetooth содержит классы для поиска устройств,
соединения и взаимодействия с ними.
- Модуль QtNetwork содержит классы для сетевого программирования.
Эти классы облегчают работу с клиентами и серверами TCP/IP и UDP, делая
сетевое программирование более легким и адаптивным.
- QtPositioning содержит классы для определения местоположения с
использованием всевозможных источников, таких как спутники, Wi-Fi или
текстовые файлы.
- Модуль Enginio реализует клиентскую библиотеку для организации
доступа к облачным сервисам Qt – Manaded Application Runtime.
- Модуль QtWebSockets содержит классы, которые реализуют протокол
WebSocket.
- QtWebKit содержит классы для реализации веб-браузера, основанного
на библиотеке WebKit2.
- Модуль QtWebKitWidgets содержит классы для WebKit1, основанные
на реализации веб-браузера, для использования в приложениях,
базирующихся на QtWidgets.
- QtXml содержит классы для работы с XML файлами. Этот модуль
предоставляет реализацию сразу для двух API: SAX и DOM.
- Модуль QtSvg содержит классы для отображения содержимого SVG-
файлов. Scalable Vector Graphics (SVG) – это язык для описания двумерной
графики и графических приложений в XML.
- Модуль QtSql предоставляет классы для работы с базами данных.
- QtTest содержит функции, которые дают возможность модульного
тестирования PyQt-приложений.

Различия PyQt4 и PyQt5


PyQt5 не имеет обратной совместимости с PyQt4; существует
несколько значительных изменений в PyQt5. Тем не менее, не так сложно
приспособить старый код к новой библиотеке. Среди прочих, существуют
следующие различия:
 Модули Python были реорганизованы. Некоторые модули были
исключены (QtScript), другие были разделены на субмодули (QtGui,
QtWebKit).
 Новые модули представлены в виде QtBluetooth, QtPositioning или
Enginio.
 PyQt5 поддерживает только новый стиль обработки сигналов и
слотов. Вызовы вида SIGNAL() или SLOT() больше не поддерживаются.
 PyQt5 не поддерживает части Qt API, которые помечены как
устаревшие в Qt v5.0.

Рассмотрим простой пример


PyQt5 является инструментом высокого уровня. Если бы мы писали это
на более низком уровне, следующий пример кода легко мог бы растянуться
на сотни строк:
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QApplication, QWidget

if __name__ == '__main__':

app = QApplication(sys.argv)

w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()

sys.exit(app.exec_())
Приведенный выше код показывает небольшое окно на экране.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
Здесь мы делаем необходимые импорты. Основные виджеты
расположены в PyQt5.QtWidgets.
app = QApplication(sys.argv)
Каждое приложение PyQt5 должно создать объект приложения
(экземпляр QApplication). Параметр sys.argv это список аргументов
командной строки. Скрипты Python можно запускать из командной строки.
Это способ, которым мы можем контролировать запуск наших сценариев.
w = QWidget()
Виджет QWidget это базовый класс для всех объектов интерфейса
пользователя в PyQt5. Мы предоставляем конструктор по умолчанию для
QWidget. Конструктор по умолчанию не имеет родителя. Виджет без
родителей называется окно.
w.resize(250, 150)
Метод resize() изменяет размеры виджета. Он стал 250 пикселей в
ширину и 150 в высоту.
w.move(300, 300)
Метод move() двигает виджет на экране на координату x=300, y=300.
w.setWindowTitle('Simple')
Здесь мы задаём заголовок нашего окна.
w.show()
Метод show() отображает виджет на экране. Виджет сначала создаётся
в памяти, и только потом (с помощью метода show) показывается на экране.
sys.exit(app.exec_())
Наконец, мы попадаем в основной цикл приложения. Обработка
событий начинается с этой точки. Основной цикл получает события от
оконной системы и распределяет их по виджетам приложения. Основной
цикл заканчивается, если мы вызываем метод exit() или главный виджет
уничтожен. Метод sys.exit() гарантирует чистый выход. Вы будете
проинформированы, как завершилось приложение.
Метод exec_ () имеет подчеркивание. Это происходит потому, что exec
является ключевым словом в python 2.

Результат отображения созданного окна

Класс QMainWindow предоставляет главное окно приложения. Он


позволяет создать классический каркас приложения со строкой состояния,
панелями инструментов и меню.
Строка состояния – это виджет, который используется для
отображения сведений о состоянии.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
class Example(QMainWindow):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.statusBar().showMessage('Ready')
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Statusbar')
self.show()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Строку состояния создают с помощью виджета QMainWindow.
self.statusBar().showMessage('Ready')
Чтобы получить строку состояния, мы вызываем метод statusBar()
класса QtGui.QMainWindow. Первый вызов метода создаёт строку состояния.
Последующие вызовы возвращают объект строки состояния. showMessage()
отображает сообщение в строке состояния.

Меню программы
Строка меню – это распространенная часть приложений с графическим
интерфейсом (GUI).
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp,
QApplication
from PyQt5.QtGui import QIcon
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(qApp.quit)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)

self.setGeometry(300, 300, 300, 200)


self.setWindowTitle('Menubar')
self.show()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
В примере выше, мы создаём строку меню с одним набором команд.
Этот набор команд будет содержать одно действие, завершающее
приложение при его выборе. Строка состояния тоже создаётся. Действие
доступно с горячей клавишей Ctrl+Q.
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
QAction – это абстракция для действий, выполняемых из меню,
панелью инструментов или с использованием горячей клавишей. В
приведённых выше трёх строках, мы создаём действие с определённой
иконкой и меткой «Exit». Кроме того, для этого действия определена горячая
клавиша. Третья строка создаёт подсказку, которая показывается в строке
состояния, когда мы наводим курсор мыши на пункт меню.
exitAction.triggered.connect(qApp.quit)
Когда мы выбираем конкретное действие, срабатывает инициирующий
сигнал. Сигнал присоединяют к методу quit() виджета QApplication. Это
завершает приложение.
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
Метод menuBar() создаёт строку меню. Мы создаём меню «File» и
добавляем в него действие выхода из приложения.
Панель инструментов
Все команды из меню, которые мы можем использовать в приложении.
Панели инструментов предоставляют быстрый доступ к большинству часто
используемых команд.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp,
QApplication
from PyQt5.QtGui import QIcon
class Example(QMainWindow):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)

self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)

self.setGeometry(300, 300, 300, 200)


self.setWindowTitle('Toolbar')
self.show()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
В вышеприведённом примере, мы создаём простую панель
инструментов. Она имеет один инструмент, действие выхода, которое
завершает приложение, будучи инициированным.
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)
В аналогичном примере как с созданием меню выше, мы создаём
объект действия. Объект имеет метку, иконку и горячую клавишу. Метод
quit() из QtGui.QMainWindow присоединяется к инициирующему сигналу.
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)
Здесь мы создаём панель инструментов и подключаем объект действия
к ней.

Панель инструментов

Совместное размещение
В примере ниже мы создадим меню, панель инструментов и строку
состояния. Мы также создадим центральный виджет.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QMainWindow, QTextEdit, QAction,
QApplication
from PyQt5.QtGui import QIcon
class Example(QMainWindow):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
textEdit = QTextEdit()
self.setCentralWidget(textEdit)
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
self.statusBar()
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exitAction)
toolbar = self.addToolBar('Exit')
toolbar.addAction(exitAction)

self.setGeometry(300, 300, 350, 250)


self.setWindowTitle('Main window')
self.show()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Этот пример кода создаёт каркас классического графического
приложения состоящей из меню, панелью инструментов и строкой
состояния.
textEdit = QTextEdit()
self.setCentralWidget(textEdit)
Здесь мы создаём виджет редактирования текста. Мы устанавливаем
его так, чтобы он был центральным виджетом QMainWindow. Центральный
виджет займёт всё оставшееся пространство.
Рисунок: Главное окно

События
Все приложения с графическим интерфейсом являются событийно-
ориентированными. События вызываются главным образом пользователем
приложения. Однако, они могут быть вызваны другими средствами, к
примеру подключением к Интернету, диспетчером окон или таймером. Когда
мы вызываем метод exec_(), приложение входит в главный цикл. Главный
цикл получает события и отправляет их объектам.
В событийной модели имеются три участника:
 Источник события;
 Объект события;
 Цель события.
Источник события – это объект, состояние которого меняется. Он
вызывает события. Объект события (событие) внедряет состояние, которое
меняется в источнике события. Цель события – это объект, которому
требуется уведомление. Объект источника события поручает задачу
обработки события цели события.
Чтобы начать работу с событиями, PyQt5 имеет уникальный механизм
сигналов и слотов. Сигналы и слоты используют для связи между объектами.
Сигнал срабатывает, когда происходит конкретное событие. Слот может
быть чем-то, вызываемым средствами Python. Слот вызывается, когда
срабатывает его сигнал.
Сигналы и слоты
Это простой пример, демонстрирующий сигналы и слоты в PyQt5.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)

class Example(QWidget):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
sld.valueChanged.connect(lcd.display)

self.setGeometry(300, 300, 250, 150)


self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
В нашем примере, мы показываем QtGui.QLCDNumber и QtGui.QSlider.
Мы меняем число lcd путём перетаскивания ползунка регулятора.
sld.valueChanged.connect(lcd.display)
Здесь мы соединяем сигнал valueChanged слайдера к слоту display
числа lcd.
Отправитель – это объект, который посылает сигнал. Получатель – это
объект, который получает сигнал. Слот – это метод, который реагирует на
сигнал.

Сигнал и слот
Переопределённый обработчик события
События в PyQt5 часто обрабатываются путём переопределённых
обработчиков события.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication
class Example(QWidget):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Event handler')
self.show()

def keyPressEvent(self, e):


if e.key() == Qt.Key_Escape:
self.close()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
В нашем примере, мы переопределяем обработчик
события keyPressEvent().
def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape:
self.close()
Если мы кликаем кнопку Esc, приложение завершается.
Отправитель события
Иногда удобно знать, какой виджет является отправителем сигнала.
Для этого, PyQt5 имеет метод sender().
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication

class Example(QMainWindow):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
btn1 = QPushButton("Button 1", self)
btn1.move(30, 50)
btn2 = QPushButton("Button 2", self)
btn2.move(150, 50)

btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)

self.statusBar()

self.setGeometry(300, 300, 290, 150)


self.setWindowTitle('Event sender')
self.show()

def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Мы имеем две кнопки в нашем примере. В методе buttonClicked() мы
определяем, какую кнопку мы нажали, с помощью метода sender().
btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)
Обе кнопки подключены к одному слоту.
def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')
Мы определяем источник сигнала путём вызова метода sender(). В
строке состояния приложения, мы показываем метку нажатой кнопки.

Отправитель события

Срабатывание сигналов
Объекты, создаваемые из QObject, могут имитировать сигналы. В
следующем примере, мы увидим, как мы может имитировать
пользовательский сигнал.
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication

class Communicate(QObject):
closeApp = pyqtSignal()

class Example(QMainWindow):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.c = Communicate()
self.c.closeApp.connect(self.close)

self.setGeometry(300, 300, 290, 150)


self.setWindowTitle('Emit signal')
self.show()

def mousePressEvent(self, event):


self.c.closeApp.emit()

if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Мы создаём новый сигнал, именуемый closeApp. Этот сигнал
испускается во время события нажатия кнопки мыши. Сигнал
присоединяется к слоту close() класса QMainWindow.
class Communicate(QObject):
closeApp = pyqtSignal()
Сигнал создаётся с pyqtSignal() как атрибут класса внешнего класса
Communicate.
self.c = Communicate()
self.c.closeApp.connect(self.close)
Пользовательский сигнал closeApp присоединяется к слоту close()
класса QMainWindow.
def mousePressEvent(self, event):
self.c.closeApp.emit()
Когда мы кликаем на окне курсором мыши, срабатывает сигнал
closeApp. Приложение завершается.
Задание к работе

На базе использования предлагаемых и самостоятельно найденных


материалов реализовать программное приложение с графическим
интерфейсом на языке Python, позволяющее:
1. Проводить решение указанным в варианте численным методом
(данные вводятся в текстовые поля, расчет осуществляется по нажатию на
кнопку).
2. Каждый новый расчет должен заноситься в новую строку таблицы.
3. По предусмотренной кнопке на базе данных в таблице строиться
график (точечный, гистограмма, линейный, на выбор).
4. По предусмотренной кнопке выполняется экспорт данных таблицы в
файл произвольного формата (txt, csv…)

Рекомендуемые источники и материалы:


PYQT
https://www.youtube.com/watch?v=3mPVcdNRUfo
https://www.youtube.com/watch?
v=pnpL9Sl79g8&list=PL1FgJUcJJ03uwFW8ys2ov2dffKs3ieGYk
https://www.youtube.com/watch?v=e5PBUFrSKgQ&list=PLZocUikpczs-
Yud2lyFpSNQOvxuPUVBDp

Graphics
https://www.youtube.com/watch?v=aPu6eK97Ios
https://www.youtube.com/watch?v=c8pQChjQ1tY
https://www.youtube.com/watch?v=Airdzeoorsg
https://www.youtube.com/watch?v=Z6jgBcRiYK4

Gauss
http://mathprofi.ru/metod_gaussa_dlya_chainikov.html
https://math.semestr.ru/gauss/gauss.php
http://kontromat.ru/?page_id=4495
Варианты:
Решить систему уравнений методом Гаусса или обратной матрицы:

Вам также может понравиться