Занятие 4
Лабораторное занятие 4¶
Логический тип данных (тип bool)¶
Логический тип данных (bool) относится к неизменяемым типам данных и переменная этого типа может принимать только два значения - True и False. Это еще один базовый тип данных.
print(1 > 0)
a = 1 > 0
print(a)
b = 1 < 0
print(b)
print(a * 5)
print(b * 3)
Логические условия можно объединять с помощью операторов & ('логическое И'), | ('логическое ИЛИ') и ~ ('логическое отрицание').
a = 1
b = 10
(a < 5) & (a<=b)
Именно тип bool используется в каскадной конструкции if elif ... else:
if 1 > 0:
print(2)
Существует приведение типов. Любое число, отличное от нуля с логической точки зрения — True, нуль воспринимается как False
if 5:
print(2)
else:
print("!")
if 0:
print(4)
else:
print("!")
for i in [1, 2, 3, 4, 5]:
print(i)
Оператор in¶
Лексема in может быть использована не только как часть синтаксической конструкции цикла for, но и как оператор для проверки принадлежности элемента итерируемому объекту:
print(4 in [1, 2, 3, 4, 5])
print(6 in [1, 2, 3, 4, 5])
print(4 in range(1, 6))
print(6 in range(1, 6))
print("b" in "abc")
print("B" in "abc")
Двумерные списки¶
"Двумерный список" — это обычный список, элементами которого являются списки. Такой термин удобен для нас, но для Python нет разницы между одномерными и двумерными списками. В частности, нечто такое вообще будет являться промежуточным: [1, [2, 3, 4], 5]
Списки элементами, которых являются другие списки называются вложенными. Например, вложенными будут списки [1, [2, 3, 4], 5] и [[1, 2, 3, 4], [5, 6], [7, 8, 9]].
Создадим список и рассмотрим обращение к элементам.
a = [[1, 2, 3], [4, 5, 6]]
print(*a)
print(a[1])
print(a[1][0])
print(a[-1][-1])
for i in range(len(a)):
print(*a[i])
Для создания списка можем использовать генераторы:
a = [[1, 2, 3] for i in range(4)]
for i in range(len(a)):
print(*a[i])
a = [[i, i+1, i+2] for i in range(4)]
for i in range(len(a)):
print(*a[i])
for x in a:
print(*x)
print(a)
Вот пример создания списка списков при помощи генератора списка, вложенного в генератор списка:
a = [[j for j in range(5)] for i in range(5)]
for x in a:
print(*x)
Упражнение 1: создайте двумерный список. Заполните его следующим образом: значение элемента - номер его строки.
Пример. Напечатаем таблицу умножения $10*10$:
n, m = 10, 10
a = [[i * j for j in range(1, m + 1)] for i in range(1, n + 1)]
for x in a:
print(*x)
Сортировка списков¶
Не углубляясь в алгоритмы, разберем, как можно сортировать списки в Python. Для этого есть функции sort и sorted. Первая изменяет сортируемый объект, вторая создает новый, а исходный остается:
a = [3, 1, 5, 4, 2]
a.sort()
print(a)
a = [3, 1, 5, 4, 2]
print(sorted(a))
print(a)
Но можем использовать вторую вместо первой:
a = [3, 1, 5, 4, 2]
a = sorted(a)
print(a)
Сортировка по ключу. key - это второй параметр функции sorted и он часто записывает в виде лямбда-функции, которая возвращает функции от объектов, которые мы используем в качестве меры этих объектов для сортировки
a = [3, 1, 5, 4, 2]
a = sorted(a, key = lambda x: -x)
print(a)
a = [[1, 5], [3, 3], [5, 5], [3, 0]]
print(sorted(a, key = lambda x: sum(x)))
a = [[1, 5], [3, 3], [5, 5], [3, 0]]
print(sorted(a, key = lambda x: x[0] ** 2 + x[1] ** 2))
Можем сортировать по нескольким параметрам в порядке убывания приоритета:
a = [[1, 6], [2, 5], [3, 4]]
print(sorted(a, key = lambda x: (sum(x), x[1])))
(sum(x), x[1]) - это кортеж. Кортежи похожи на списки, но они неизменяемы (нельзя присваивать по индексу и добавлять элементы)
a = [1, 2]
a[1] = 3
print(a)
a = (1, 2)
a[1] = 3
print(a)
a = [1, 2]
a.append(3)
print(a)
a = (1, 2)
a.append(3)
print(a)
a = [1, 2]
a = [3, 4]
print(a)
a = (1, 2)
a = (3, 4)
print(a)
Строки сортируются в лексикографическом порядке:
a = ["100", "11", "12", "120", "119"]
print(sorted(a))
a = ["100", "11", "12", "120", "119"]
print(sorted(a, key = lambda x: int(x)))
Функции, возвращающие значение¶
Функция в python - объект, принимающий аргументы и возвращающий значение. Обычно функция определяется с помощью инструкции def.
По сути функции - это вспомогательные алгоритмы.
Любая функция/метод (про методы Вы узнаете позже) всегда возвращает какое-либо значение. Если возвращаемого значения нет, то возвращается None. Выбор между использованием return, return None или отсутствием return в функции зависит от личного стиля кодирования и требований к читаемости кода.
Логическое значение как результат работы функции¶
Ниже описаны три аналогичных функции. Прочитайте их тела и объясните почему они работают одинаково. Какая из них вам больше нравится?
def is_positive(x):
if x > 0:
return True
else:
return False
print(is_positive(5))
print(is_positive(-5))
def is_positive(x):
if x > 0:
return True
return False
print(is_positive(5))
print(is_positive(-5))
def is_positive(x):
return x > 0
print(is_positive(5))
print(is_positive(-5))
Анонимные функции (lambda-функции)¶
Лямбда-функции в Python являются анонимными. Это означает, что функция безымянна. Как известно, ключевое слов def используется в Python для определения обычной функции. В свою очередь, ключевое слово lambda используется для определения анонимной функции.
Лямбда-функции задаются следующим образом:
Lambda аргументы: выражение
Лямбда-функции могут иметь любое количество аргументов, но у каждой может быть только одно выражение.
double = lambda x: x*2
print(double(5))
Функции как аргументы функций map, reduce и filter¶
Для поэлементной обработки любого итерируемого объекта можно использовать функции map и filter.
Функция map() используется для применения функции к каждому элементу итерируемого объекта (например, списка или словаря) и возврата нового итератора для получения результатов.
Синтаксис функция map() следующий:
map(function, iterable, [iterable 2, iterable 3, ...])
Функция filter() применяет другую функцию к заданному итерируемому объекту (список, строка, словарь и так далее) и проверяет нужно ли сохранить конкретный элемент или нет. Другими словами, она отфильтровывает то, что не проходит и возвращает все остальное.
Функция reduce() принимает в качестве аргументов функцию и список. Функция вызывается с помощью лямбда-функции и итерируемого объекта и возвращается новый уменьшенный результат. Так выполняется повторяющаяся операцию над парами итерируемых объектов. Функция reduce() входит в состав модуля functools.
a = "1 2 -3 4 -5".split()
print(a)
a = list(map(int, a))
print(a)
a = "1 2 -3 4 -5".split()
print(a)
a = list(map(float, a))
print(a)
a = "1 2 -3 4 -5 0".split()
print(a)
a = list(map(bool, a))
print(a)
a = "1 2 -3 4 -5 0".split()
print(a)
a = list(map(int, a))
print(a)
a = list(map(bool, a))
print(a)
Как параметр для map можно передавать не только стандартные функции, но и свои собственные:
def my_function(x):
return x * 2
a = "1 2 -3 4 -5".split()
print(a)
a = list(map(my_function, a))
print(a)
Такие "одноразовые функции" загрязняют пространство имён, поэтому есть возможность создать безымянную функцию при помощи слова lambda. Вычисляясь, лямбда-выражение "изготавливает" новую функцию и передаёт её как объект туда, где она нужна — в функцию map. Затем она сразу забывается.
a = "1 2 -3 4 -5".split()
print(a)
a = list(map(lambda x: x * 2, a))
print(a)
from functools import reduce
current_list = [5, 15, 20, 30, 50, 55, 75, 60, 70]
summa = reduce((lambda x, y: x + y), current_list)
print(summa)
a = [1, 2, -3, 4, -5]
b = list(map(lambda x: x > 0, a))
c = list(filter(lambda x: x > 0, a))
print(b)
print(c)
Можем делать "сложную" лямбда-функцию:
a = "1 2 -3 4 -5".split()
print(a)
a = list(map(lambda x: abs(int(x)), a))
print(a)
# Дан список чисел
numbers = [10, 2, 3, 55, 70, 8, 10, 1]
# функция, которая проверяет числа
def filter_odd_num(in_num):
if(in_num % 2) == 0:
return True
else:
return False
# Применение filter() для удаления нечетных чисел
out_filter = filter(filter_odd_num, numbers)
print("Тип объекта out_filter: ", type(out_filter))
print("Отфильтрованный список: ", list(out_filter))
Упражнение 2: считайте список с клавиатуры. С помощью функции filter удалите из него те элементы, которые не являются квадратами однозначных натуральных чисел.
Можно использовать map для обработки считанного списка. Считываем с помощью функции input() объект типа str, к нему применяем метод split() и получаем list, ко всем его элементам функция map применяет функцию int, а конструктор списка list сохраняет результат в список:
a = list(map(int, input().split()))
print(a)
a = [list(map(int, input().split())) for i in range(5)]
for x in a:
print(*x)
Пример: удалить из матрицы строки с отрицательной суммой
a = [[5, -2, 3], [-1, 2, -3], [-8, 4, 5]]
for x in a:
print(*x)
a = list(filter(lambda x: sum(x) >= 0, a))
print(a)
print(sum(a[0]), sum(a[1]))
И еще примеры:
a = [1, 2, 3, 4, 5]
print(list(map(lambda x: x ** 2, a)))
a = [1, 2, -3, 4, -5]
print(list(map(lambda x: x if x >= 0 else 0, a)))
Цикл while. Целочисленная арифметика¶
Кроме цикла for в Python используется цикл while. Например, он удобен, если нужно указать условие выхода через условие типа bool
i = 0
while i < 5:
print(i ** 2)
i += 1
for i in range(5):
print(i ** 2)
Еще две арифметические операции, которые потребуются в примере ниже: деление с остатком и целочисленное деление.
print(16 % 3)
print(16 // 3)
С помощью цикла while удобно обращаться к отдельным цифрам числа. Например, можно сохранить их в массив:
a = []
n = 2345
while n > 0:
a.append(n % 10)
n = n // 10
print(a)
Упражнение 3: напишите функцию, которая вычисляет сумму цифр числа, считайте число с клавиатуры и примените эту функцию.
Можно запустить "бесконечный цикл" (он ничем не отличается от обычного). Внутри циклов можно использовать конструкции break и continue:
while True:
a = int(input())
print(a)
Для прерывания работы ячейки можно нажать на квадратик.
while True:
a = int(input())
if a > 0:
print(a)
else:
break
while True:
a = int(input())
if a > 0:
continue
else:
break
Генераторы и отложенные вычисления¶
def foo(x):
print(f"foo called for {x}")
return x * 10
for x in map(foo, [1, 2, 3]):
print(x)
def foo(x):
print(f"foo called for {x}")
return x * 10
def boo(x):
print(f"foo called for {x}")
return x + 1000
A = [1, 2, 3]
B = map(foo, A)
C = map(boo, B)
print("Iterations start:")
for x in C:
print(x)
Итерируемые объекты¶
Часто бывает удобно использовать распаковку переменных:
a, b = 1, 2
print(a)
print(b)
a, b, c = [1, 2, 3]
print(a)
print(b)
print(c)
a, b, c = [1, 2, 3, 4, 5]
*a, b, c = [1, 2, 3, 4, 5]
print(a, b, c)
a, *b, c = [1, 2, 3, 4, 5]
print(a, b, c)
a, b, *c = [1, 2, 3, 4, 5]
print(a, b, c)
for a, b, c in [(1, 2, 3), (4, 5, 6), (7, 8, 9)]:
print(a, b, c)
for a, *b in [(1, 2, 3, 4), (10, 20), (100, 200, 300)]:
print(a, b)
a, (b, c) = [1, (2, 3)]
print(a, b, c)
enumerate, zip, for с распаковкой¶
В цикле for также можно использовать распаковку:
a = [[1, 2], [3, 4], [5, 6]]
for x, y in a:
print(x, y, x + y)
Часто такая распаковка используется не сама по себе, а вместе с использованием удобных функций zip и enumerate, которые позволяют удобнее работать со списками:
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [0, 0, 0]]
for i, x in enumerate(a):
print(i, x, sum(x))
with open("1.txt", "w") as f:
f.writelines([word + "\n" for word in ["dog", "cat", "mouse", "duck", "goose"]])
for line in open("1.txt"):
print(line.strip())
for i, x in enumerate(open("1.txt")):
print(i, x.rstrip())
a = ["ab", "cd", "ef"]
b = [1, 2, 3]
print(list(zip(a, b)))
for a, b in zip("abcde", range(5)):
print(a, b)
for a, b in zip("abcde", range(10)):
print(a, b)
Модуль itertools¶
Для более удобной работы с итерируемыми объектами мы можем использовать библиотеку itertools. Для этого нужно ее импортировать:
import itertools as it
for x, y, z in it.permutations("ABC"):
print(x, y, z, sep='')
for x, y, z in it.permutations("ABCD", 3):
print(x, y, z, sep='', end=' ')
Дополнительно по itertoolsможно посмотреть: https://proglib.io/p/iteriruemsya-pravilno-20-priemov-ispolzovaniya-v-python-modulya-itertools-2020-01-03
Упражнение 4:
Вычислите с помощью it.permutation $C_{12}^{5}$
for x, y in it.combinations("ABCDE", 2):
print(x, y, sep='', end=' ')
for x, y in it.combinations_with_replacement("ABCDE", 2):
print(x, y, sep='', end=' ')
for a in it.chain("мама", "мыла", "раму"):
print(a, end=' ')
for a in it.chain([5, 4, 3], [3, 4, 5], [[3, 4, 5]]):
print(a, end=' ')
for n, s in it.product("wxyz", "ABC"):
print(n, s)
Упражнение 5:
Введите 2 списка (координаты вектора a и координаты вектора b) и найдите скалярное произведение этих векторов, используя zip или что-нибудь из itertools.
Упражнение 6:
Студент составляет 4-буквенные слова из букв A, B, E, F, L, U. Каждую букву можно использовать не более одного раза, при этом в слове нельзя использовать более одной гласной. Сколько различных кодов может составить студент?При решении используйте itertools.
Упражнение 7:
Составьте все возможные пары из элементов строк '123456' и 'abcdef' такие, что первый элемент пары из числовой строки, а второй из текстовой. При решении используйте itertools.
Упражнение 8: Если выписать все натуральные числа меньше 10, кратные 3 или 5, то получим 3, 5, 6 и 9. Сумма этих чисел равна 23.
Найдите сумму всех чисел меньше 1000, кратных 3 или 5. Предложите не менее 3-х вариантов решения.
Упражнение 9: Сгенерируйте список используя чисел от -10 до 1000 с шагом 2. Выберите только элементы с чётными индексами. После этого используя функцию reduce и lambda-функцию найдите произведение элементов полученного списка.
Упражнение 10: Сгенерируйте список используя чисел от -10 до 1000 с шагом 2. Выберите только элементы с нечётными индексами. После этого используя функцию map возведите в квдрат каждый элемент полученноо списка.