Занятие 2
Практическое занятие 2: Основы языка Python¶
Цель: Рассмотреть основы языка Python¶
Задачи:¶
- Рассмотреть типы данных Python
- Освоить использование арифметических операций, операций сравнения, операций над строками и логичеких операций в Python
- Получить практику в целочисленной арифметике
- Освоить использование цикла while
- Рассмотреть многоуровневое и каскадное ветвления
- Познакомиться с аргументами функции
range()
- Освоить ряд арифметических алгоритмов: определение простоты числа, разложение на простые множители и алгоритм Евклида
Типы данных Python¶
Рассмотрение типов данных языка Python мы начнем с числового и строкового. Числа записываются последовательностью цифр, также перед числом может стоять знак минус, а строки записываются в одинарных кавычках. Таким образом, 2 и '2' — это разные объекты, первый объект — целое число (тип int), а второй — строка (тип str).
Операция +
для целых чисел и для строк работает по-разному: для чисел это сложение, а для строк — конкатенация (выполните код в ячейках ниже):
2 + 2
'2' + '2'
Кроме целых чисел (тип int) есть и другой класс чисел: действительные (вещественные числа, тип float), представляемые в виде десятичных дробей. Они записываются с использованием десятичной точки, например, 2.0. Объекты 2 и 2.0 имеют равные значение, но это — разные объекты. Например, можно вычислить значения выражения 'ABC' 10 (повторить строку 10 раз), но нельзя вычислить 'ABC' 10.0:
'ABC' * 10
'ABC' * 10.0
Определить тип объекта можно при помощи функции type()
:
type(5)
type(5.0)
type('5')
type(5 < 10)
Представление чисел в различных системах счисления¶
Язык Python позволяет оперировать непосредственно с числами, представленными в некоторых системах счисления.
Например, с помощью префикса 0b
можно записать число в двоичной системе счисления, с префиксом 0o
— в восьмеричной системе, а с 0x
— в шестнадцатеричной системе счисления.
Исполните ячейки ниже:
0b11111111
0b00000001 + 0b00000011
0o1234567
0xffff
Функции bin()
, oct()
и hex()
позволяют преобразовать целое число из десятичной в двоичную, восьмеричную и шестнадцатиричную системы счисления, соответственно. Результат будет представлен в виде строки цифр с соответствующим префиксом:
bin(168)
oct(168)
hex(255)
Операции для чисел¶
В таблице ниже приведены основные перации для чисел:
Операция | Действие |
---|---|
A + B | сумма |
A - B | разность |
A * B | произведение |
A / B | частное |
A ** B | возведение в степень |
Полезно помнить, что квадратный корень из числа x — это x ** 0.5
, а корень степени n это x ** (1 / n)
.
Есть также унарный вариант операции -
, то есть операция с одним аргументом. Она возвращает число, противоположное данному. Например: -A.
В выражении может встречаться много операций подряд. Как в этом случае определяется порядок действий? Например, чему будет равно 1 + 2 * 3 ** 1 + 1
? В данном случае ответ будет 8, так как сначала выполняется возведение в степень, затем – умножение, затем — сложение.
Более общие правила определения приоритетов операций:
- Выполняются возведения в степень справа налево, то есть
3 ** 3 ** 3
это $$ 3^{(3^{3})}. $$ - Выполняются унарные минусы (отрицания).
- Выполняются умножения и деления слева направо. Операции умножения и деления имеют одинаковый приоритет.
- Выполняются сложения и вычитания слева направо. Операции сложения и вычитания имеют одинаковый приоритет.
Задачи¶
Задача 1: запишите в ячейку ниже код, вычисляющий следующее выражение: $$ 2583600 + 389*487 - \frac{25^{80}}{1250} $$
Задача 2: запишите в ячейку ниже код, вычисляющий следующее выражение: $$ \sqrt{98} - 3.14*\frac{25^{15^{3^{2}}}}{(153.6-17.6*9.7)} $$
Задача 3: в ячейке ниже напишите код, вычисляющий следующее выражение: $$ 3,58 - \frac{\ln{89}}{358} $$
Строки¶
Как уже сказано выше, литералы объектов типа str
записываются в апострофах или в кавычках. Строкой называется последовательность символов: букв, цифр, знаков препинания и т.д.:
print('Это строка')
Операции над строками¶
Операция | Действие |
---|---|
A + B | конкатенация |
A * n | повторение n раз |
Значение n должно быть целым и неотрицательным.
Задача 4: запишите в ячейку ниже код, формирующий предложение из строк 'снегирей', 'расселась', 'калины', 'стайка', 'ветках', 'На', ' ' с помощью операций над строками:
Целочисленная арифметика¶
Для целых чисел определены операции +
, -
, *
, /
, и **
. Операция деления /
для целых чисел возвращает значение типа float. Также функция возведения в степень возвращает значение типа float, если показатель степени — отрицательное число.
Но есть и специальная операция целочисленного деления, выполняющегося с отбрасыванием дробной части, которая обозначается //
. Она возвращает целое число: целую часть частного. Например:
21 // 4
-21 // 4
Обратим внимание, что совершая операцию целочисленного деления на 10 для числа, записанного в десятичной системе счисления, мы отбрасываем младший разряд (выполните код ниже):
152 // 10
Другая близкая ей операция: это операция взятия остатка от деления, обозначаемая %
:
21 % 4
-21 % 4
Объясните значение в ячейке выше.
Обратим внимание, что совершая операцию взятия остатка от деления на 10 для числа, записанного в десятичной системе счисления, мы выделяем цифру младшего разряда (выполните код ниже):
152 % 10
Преобразование типов¶
Иногда бывает полезно целое число записать, как строку. И, наоборот, если строка состоит из цифр, то полезно эту строку представить в виде числа, чтобы дальше можно было выполнять арифметические операции с ней. Для этого используются функции, одноименные с именем типа, то есть int()
, float()
, str()
. Например, int('123') вернет целое число 123, а str(123) вернет строку '123'.
Выполните ячейку ниже и объясните полученный результат:
str(2 + 2) * int('2' + '2')
Функция преобразования типа int()
может использоваться для преобразования строки, содержащей число в произвольной системе счисления в десятичное число. Например, код ниже преобразует строку с записью числа в шестнадцатиричной системе счисления в десятичное число:
int('0xFF', base=16)
Префикс можно и исключить, поэкспериментируйте с преобразованием чисел из различных систем счисления, не забывая указывать основание — параметр base
:
Логический тип¶
Следующий тип - логический (bool). Величина логического типа может принимать только одно из двух значений: в Python это значения True и False. Величина типа bool является результатам перечисленных ниже операций сравнения:
Операция | Действие |
---|---|
> | Возвращает True, если первый операнд больше второго. Иначе — False. |
>= | Возвращает True, если первый операнд больше или равен второму. Иначе — False. |
< | Возвращает True, если первый операнд меньше второго. Иначе — False. |
<= | Возвращает True, если первый операнд меньше или равен второму. Иначе — False. |
== | Возвращает True, если оба операнда равны. Иначе — False. |
!= | Возвращает True, если оба операнда НЕ равны. Иначе — False. |
Выполните код в ячейке ниже. Измените операцию сравнения в примере — посмотрите на результаты.
5 >= 8
Логические операции¶
Выражение типа 5 >= 8
называется простым логическим выражением, так оно содержит одну операцию сравнения. Можно формировать сложные логические выражения с помощью логических операций and, or и not:
Операция | Действие |
---|---|
and | Логическое И |
or | Логическое ИЛИ |
not | Логическое отрицание |
Выполните ячейку ниже для разных числовых значений — проанализируйте результаты.
(5 >= 8) and (8 < 9)
В данном выражении скобки можно не ставить, поскольку приоритет логической операции ниже, чем операторов сравнения. Напишите это выражение сами:
Выполните ячейку ниже для разных логических значений — проанализируйте результаты.
False and True
Задачи¶
Задача 5: в ячейке ниже напишите код, который строит таблицу всех значений логической операции and
(таблицу истинности)
Выход (первые три строки):
A, B, A and B
False, False, False
False, True, False
Задача 6: в ячейке ниже напишите код, который строит такую же таблицу всех значений логической операции or
Задача 7: в ячейке ниже напишите код, который строит такую же таблицу всех значений логической операции not
Идентификаторы и переменные¶
Идентификатор — это имя некоторого объекта (переменной, функции и проч.) в программе, позволяющее отличать его от других объектов.
Идентификаторы в Python не ограничены по длине и чувствительны к регистру: A
и a
— это разные идентификаторы.
В идентификаторах допустимы только символы от A
до Z
в верхнем и нижнем регистре, подчеркивание _
и, кроме первого символа идентификатора, цифры от 0
до 9
.
Иденитификатор _1position
корректен, а идентификатор 1position
— нет.
Для хранения промежуточных или конечных результатов в программе используются переменные
. Для создания переменной в Python достаточно придуметь для нее идентификатор (имя переменной) и присвоить
ей значение с помощью оператора связывания
=
.
Например, в коде ниже создается переменная length
, которая хранит значение длины стороны квадрата, а затем величина периметра квадрата сохраняется в переменной perimeter
— выполните его в ячейке ниже.
length = 100
perimeter = 4 * length
print('Периметр квадрата со стороной ' + str(length) + ' равен: ' + str(perimeter))
Мы назвали оператор =
оператором связывания
, потому что переменная в Python является лишь ссылкой на объект в памяти. При создании любой переменной (число или строка) идентификатор связывается со значением — а само значение находится где-то в оперативной памяти. При таком подходе тип переменной может изменяться в разных частях программы — выполните пример в ячейке ниже:
Пример:
x = 'abc'
print('x = ' + x + ', ' + str(type(x)))
x = 5
print('x = ' + str(x) + ', ' + str(type(x)))
Если надо выполнить арифметическую операцию над переменной и полученный результат записать в ту же переменную, можно использовать краткую форму записи арифметических операций:
Полная форма | Краткая форма |
---|---|
A = A + B | A += B |
A = A - B | A -= B |
A = A * B | A *= B |
A = A / B | A /= B |
A = A // B | A //= B |
A = A % B | A %= B |
Ввод данных с клавиатуры: функция input()¶
Чаще всего переменные получают свои значения из внешних источников: клавиатура, файлы.
В Python для ввода данных с клавиатуры используется функция input()
, которая считывает строку с клавиатуры и возвращает значение считанной строки, которое сразу же можно присвоить переменной — выполните ячейку:
x = input()
x = 2 * x
print(x)
Если результат оказался для Вас неожиданным, то все дело в том, что функция input()
возвращает текстовую строку.
Для выполнения арифметических операций необходимо преобразовать результат функции input()
в число с помощью функций преобразования типов int()
или float()
:
x = int(input())
x = 2 * x
print(x)
Вывод данных: функция print()¶
Уже используемая нами для вывода значений функция print()
, может выводить не только значения переменных, но и значения любых выражений. Например, допустима запись print(3 * 2) — попробуйте вычислить разные выражения в ячейке ниже:
Также при помощи функции print()
можно выводить значение не одного, а нескольких выражений, для этого нужно перечислить их через запятую:
length = 100
perimeter = 4 * length
print('Периметр квадрата со стороной ', str(length), ' равен: ', str(perimeter))
Выводимые значение разделяются одним пробелом. Но такое поведение можно изменить: можно разделять выводимые значения любым другим символом или не разделять никак. Для этого нужно функции print()
передать специальный параметр sep, равный строке, используемый в качестве разделителя. По умолчанию параметр sep равен строке из одного пробела и между значениями выводится пробел. Чтобы использовать в качестве разделителя, например, переход на новую строку, нужно передать параметр sep, равный \n
:
length = 100
perimeter = 4 * length
print('Периметр квадрата со стороной ', str(length), ' равен: ', str(perimeter), sep='\n')
Цикл while¶
На прошлом занятии мы рассмотрели конструкцию цикла for
. Сегодня пришло время цикла while
(цикл пока).
Цикл while
состоит из логического выражения (см. ниже) после ключевого слова while и тела цикла:
while логическое выражение:
команды
тела
цикла
сдвинуты
вправо
команда_вне_цикла
Тело цикла выполняется до тех пор, пока
логическое выражение истинно.
Цикл while
используется в тех случаях, когда число итераций заранее неизвестно.
В задачах ниже Вы должны использовать именно цикл while
, так как число итераций зависит от конкретного пользовательского ввода.
Пример применения цикла while
для вычисления цифр числа в семеричной системе счисления.
Объясните, почему они выводятся в обратном порядке:
x = int('123456', base=7)
while x != 0:
last_digit = x % 7
print(last_digit)
x = x // 7
Задача 8: в ячейке ниже напишите код, который вычисляет цифры числа в пятеричной системе счисления
Вход: число в пятеричной системе счисления (вводится с клавиатуры)
Выход: цифры введенного числа
Задача 9: в ячейке ниже напишите код, который подсчитывает количество цифр введенного натурального числа (десятичная система счисления)
Многоуровневое и каскадное ветвление¶
На прошлом занятии мы познакомились с конструкцией ветвления. Вспомним этот материал, решив задачу ниже:
Задача 10: напишите код, который находит большее из двух введенных с клавиатуры чисел
Теперь усложним задачу, написав код, который находит большее из трех введенных с клавиатуры чисел. Решение может выглядеть, например, как в ячейке ниже — выполните его.
a = float(input('Введите первое число: '))
b = float(input('Введите второе число: '))
d = float(input('Введите третье число: '))
if a >= b:
if a >= d:
print('Большее из трех — ', a)
else:
print('Большее из трех — ', d)
else:
if b >= d:
print('Большее из трех — ', b)
else:
print('Большее из трех — ', d)
Выше пример многоуровневого ветвления — когда внутри ветки if/else одного ветвления находится другое ветвление. Глубина подобного вложения может быть любой.
Когда таких уровней вложения много программа начинает выглядеть громозко и на выручку приходит каскадная конструкция с использованием ключевых слов if, elif, else. Ветка elif выполняется только в том случае, когда проверка предыдущего условия вернула False.
Решим предыдущую задачу с помощью каскажного ветвления:
a = float(input('Введите первое число: '))
b = float(input('Введите второе число: '))
d = float(input('Введите третье число: '))
if a >= b and a >= d:
print('Большее из трех — ', a)
elif d >= a and d >= b:
print('Большее из трех — ', d)
elif b >= a and b >= d:
print('Большее из трех — ', b)
else:
print('Такого не может быть')
Задача 11: используя вложенное и каскадное ветвление, напишите код, который по введенному номеру месяца печатает его название или выводит сообщение о некорректном вводе
Задача 12: используя функцию ввода с клавиатуры, напишите программу нахождения корней квадратного уровнения:
$$
a*x^2 + b*x + c = 0
$$
Вход: значения коэффициентов a, b, c, который вводятся с клавиатуры
Выход: значения корней квадратного уравнения или сообщение об их отсутствии
Функция range()
¶
На прошлом занятии в заголовке цикла for мы использовали вызов функции range()
с одним аргументом — числом итераций:
sum = 0
for i in range(5):
sum = sum + i
print(sum)
В подобных примерах функция range()
создает арифметическую последовательность, по значениям которой "пробегает" переменная цикла. Выполните ячейку ниже, чтобы убедиться в этом.
for i in range(5):
print(i)
На самом деле функция имеет три параметра — range(start, stop, step)
:
start
— начальный член,stop
— ограничитель (значение не включается в прогрессию!),step
— шаг прогрессии (может быть отрицательным)
Примеры:
for i in range(1, 8, 2):
print(i)
for i in range(10, 1, -3):
print(i)
Параметры start и step имеют значения по умолчанию:
start = 0
step = 1
for i in range(2, 8):
print(i)
Проверка числа на простоту¶
Напомним, что простое число (prime number) — это натуральное число больше 1, у которого есть всего два делителя: единица и само число. Проверку числа на простоту оформим в виде функции, которая будет возвращать True для простых чисел и False для составных. Алгоритм "в лоб" заключается в том, что для проверяемого числа n перебираются все натуральные числа, начиная с 2, пока не найдем делитель числа n. Если этот делитель будет равен n, то число будет простым, иначе у n есть нетривиальный делитель и число n будет составным:
def IsPrime(n):
d = 2
while n % d != 0:
d += 1
return d == n
Задача 13: Запишите в ячейку ниже код, принимающий с клавиатуры исходное число n и выводящий сообщение является ли число простым.
Используйте код функции IsPrime()
— выполните её для разных значений n.
Алгоритм остановится на числе, которое будет делителем числа n. Если алгоритм остановился на числе n, то число n простое, иначе — составное. Сложность этого алгоритма — $O(n)$. Lнный алгоритм можно оптимизировать, если учесть, что у любого составного числа есть собственный (то есть не равный 1) делитель, не превосходящий квадратного корня из числа. Это позволит сократить сложность алгоритма до $O(\sqrt{n})$:
ef IsPrime(n):
d = 2
while d * d <= n and n % d != 0:
d += 1
return d * d > n
Задача 14: Измените код задачи 13, использовав оптимизированный алгоритм проверки на простоту:
Факторизация числа¶
Разложение числа на простые множители называется факторизацией. Факторизация целых чисел обеспечивается основной теоремой арифметики, в которой утверждается существование и единственность разложения любого числа на простые множители. Факторизацию числа можно осуществить методом перебора его простых делителей подобно проверки простоты числа: произвести перебор всех целых чисел от 2 до квадратного корня из факторизуемого числа n и в вычислении остатка от деления n на каждое из этих чисел. Если остаток от деления на некоторое число m равен нулю, то m является делителем n. В этом случае n сокращается на m и процедура повторяется. По достижении квадратного корня из оставшегося числа и невозможности сократить его ни на одно из меньших чисел, оно объявляется простым и также приписывается к простым сомножителям исходного числа n:
def factorize(n):
d = 2
while d ** 2 <= n:
if n % d == 0:
n //= d
print(d)
else:
d += 1
if n != 1:
print(n)
Задача 15: Запишите в ячейку ниже код, принимающий с клавиатуры исходное число n и выводящий список простых делителей числа n.
Используйте код функции factorize()
— выполните код для разных значений n.
Алгоритм Евклида¶
Рассмотрим задачу нахождения наибольшего общего делителя двух натуральных чисел. Постановка задачи — даны два натуральных числа a и b, необходимо найти такое наибольшее число d, которое является делителем каждого из этих чисел. Задача эффективно решается с использованием алгоритма Евклида. Он основан на следующем свойстве (обозначим наибольший общий делитель чисел a и b как НОД(a, b)): $$НОД(a, b) = НОД(a-b, b)$$ Реализация алгоритма Евклида с помощью цикла while будет выглядеть следующим образом:
def euclid(a, b):
while a != 0 and b != 0:
if a > b:
a = a - b
else:
b = b - a
return max(a, b)
В коде выше использована встроенная функция нахождения максимума max()
.
Задача 16: Запишите в ячейку ниже код, принимающий с клавиатуры два числа a, b и выводящий НОД(a, b).
Используйте код функции euclid()
— выполните код для разных значений пар a, b.
Алгоритм выше можно оптимизировать приняв во внимание, что многократное вычитание из большего числа меньшего закончится на числе, которое является остатком от деления двух первоначальных чисел. То есть в алгоритме можно заменить операцию вычитания на взятие остатка:
def euclid_1(a, b):
while a != 0 and b != 0:
if a > b:
a = a % b
else:
b = b % a
return max(a, b)
Задача 17: Запишите в ячейку ниже код, принимающий с клавиатуры два числа a, b и выводящий НОД(a, b).
Используйте код функции euclid_1()
— выполните код для разных значений пар a, b.