Домашнее задание №6#

Warning

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

В рамках домашнего задания №6 от вас требуется решить 13 задач

  1. Чет, нечет;

  2. Сумма элементов;

  3. Числа с цифрой 6;

  4. Список нескрытых файлов;

  5. Попарные суммы элементов двух списков;

  6. Попарные суммы элементов одного списка;

  7. Сумма по строкам;

  8. Сумма по столбцам*;

  9. Диагонали матрицы;

  10. Скалярное произведение;

  11. \(l_p\) норма;

  12. Счет вверх и вниз;

  13. Итератор по соседним элементам.

На усмотрение студента предлагается решить ещё и задачи из необязательной части.

1. Чет, нечет#

Пусть дан список v положительных целых чисел. С помощью спискового включения сгенерируйте другой список, где каждое четное заменится на строку "even", а нечетное на строку "odd".

def odd_even(v: list[int]) -> list[str]:
    return [
        # ваш код
    ]

numbers = [1, 3, 2]
print(odd_even(numbers)) # ["odd", "odd", "even"]

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

2. Сумма нечетных элементов#

С помощью списковых включений вычислите сумму всех нечетных (по значению) элементов списка.

def sum_odds(v: list[int]) -> int:
    pass

L = [3, 7, 2, 4, 5, 6] 
print(sum_odds(L)) # 15

3. Числа с цифрой 6#

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

def contains_digit_six(v: list[int]) -> list[int]:
    return [
        # ваш код
    ]

v = [5, 6, 15, 51, 16, 61, 66, -5, -6]
print(contains_digit_six(v)) # [6, 16, 61, 66, -6]

4. Список нескрытых файлов#

В Unix-like операционных системах файлы и папки, названия которых начинаются с точки (.), считаются скрытыми. С помощью спискового включения отфильтруйте таковые из результата функции os.listdir.

def nonhidden(path):
    return [
        # ваш код
    ]

5. Попарные суммы элементов двух списков#

Пусть есть два списка чисел \(u\) и \(v\). Верните сумму \(x_1 + x_2\) для каждой возможной пары элементов \((x_1, x_2)\), где \(x_1\in u\), а \(x_2\in v\).

def outer_sum(u: list[float], v: list[float]) -> list[float]:
    return [
        # ваш код
    ]

u = [0, 1, 2]
v = [100, 200, 300]
print(outer_sum(u, v)) # [100, 200, 300, 101, 201, 301, 102, 202, 302]

6. Попарные суммы элементов одного списка#

Пусть дан список чисел \(v\). Найдите \(\{x + y| x, y \in v\}\).

def choice2_sum(v: list[float]) -> list[float]:
    return [
        # ваш код
    ]

L = [1, 7, 42]
print(choice2_sum(L)) # [2, 8, 43, 8, 14, 49, 43, 49, 84]

7. Сумма по строкам#

Пусть дана прямоугольная матрица чисел matrix в виде списка списков. Верните список сумм каждой из строк этой матрицы (эквивалент np.sum(matrix, axis=1)).

def rowwise_sum(matrix: list[list[float]]) -> list[float]:
    return [
        # ваш код
    ]

matrix = [[1, 2], [3, 4]]
print(rowwise_sum(matrix)) # [3, 7]

8. Сумма по столбцам#

Пусть дана прямоугольная матрица чисел matrix в виде списка списков. Верните список сумм каждой из строк этой матрицы (эквивалент np.sum(matrix, axis=0)).

def columnwise_sum(matrix: list[list[float]]) -> list[float]:
    return [
        # ваш код
    ]

matrix = [[1, 2], [3, 4]]
print(columnwise_sum(matrix)) # [4, 6]

9. Диагонали матрицы#

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

def major_diagonal(matrix: list[list[float]]) -> list[float]:
    return [ 
        # ваш код 
    ]

def minor_diagonal(matrix: list[list[float]]) -> list[float]:
    return [
        # ваш код
    ]


matrix = [[1, 2], [3, 4]]
print(major_diagonal(matrix)) # [1, 4]
print(minor_diagonal(matrix)) # [2, 3]

10. Скалярное произведение#

Пусть даны два списка чисел \(u\) и \(v\). Используя списковое включение, найдите их скалярное произведение.

def dot_product(u: list[float], v: list[float]) -> float:
    pass

u = [1, 2]
v = [3, 4]

print(dot_product(u, v)) # 11

11. \(l_p\) норма#

В пространстве \(l_p\) (\(p\geq1\)) норма вектора \(\vec{v}=\bigl(v_1, \ldots, v_n \bigr)\) определяется формулой

\[ \|\vec{v}\| = \left(\sum_{i=1}^n |v_i|^p\right)^{\tfrac{1}{p}}. \]

Определите функцию norm вычисляющую \(l_p\) норму.

def norm(v: list[float], p: float) -> float:
    pass

v = [3, 4]
print(norm(v, 2)) # 5.0

12. Счет вверх и вниз#

Напишите генератор, который считает от 0 до n, а затем в обратном порядке.

def UpAndDown(n: int):
    # ваш код здесь

print(list(UpAndDown(3))) # [0, 1, 2, 3, 2, 1, 0]

13. Итератор по соседним элементам#

Реализуйте итератор/генератор, который позволит итерировать сразу парами соседних элементов, т.е. для списка [A, B, C, D]:

  1. первая итерация A и B — первый и второй элементы списка;

  2. вторая итерация B и C — второй и третий элементы списка;

  3. третья и последняя итерация C и D — третий и четвертый элементы списка.

def prev_next(iterable):
    # ваш код здесь

x = ["A", "B", "C", "D"]
print(list(prev_next(x))) # [("A", "B"), ("B", "C"), ("C", "D")]

Необязательная часть#

Логирующий декоратор#

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

Декоратор, проверяющий тип#

Напишите параметризованный декоратор typed для функций одного аргумента, который бросает исключение TypeError, если функция вызвана с аргументом не того типа, который был указан в декораторе.

def typed(type_):
    # ваш код здесь

@typed(str)
def paint_red(x):
    color_red = "\033[91m"
    color_end = "\033[0m"
    return "".join([color_red, x, color_end])

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

print(paint_red("Текст красным цветом"))
Текст красным цветом

Note

В IDE и на сайте текст останется исходного цвета.

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

try:
    paint_red(42)
except TypeError as msg:
    print(msg)
Функция paint_red вызвана с неправильным типом аргумента int. Ожидался тип str.

Если func — имя декорируемой функции, x — имя её аргумента, а type_ — параметр, задающий тип этого аргумента в декораторе, то бросить необходимое исключение можно инструкцией

error_msg = "Функция {} вызвана с неправильным типом аргумента {}. Ожидался тип {}."
raise TypeError(error_msg.format(
    func.__name__,
    type(x).__name__,
    type_.__name__
))

Диапазон действительных чисел#

Реализуйте генератор, который будет аналогичен range, но будет принимать и целые и действительные числа (аналог np.arange). Генератор должен работать для произвольной комбинации значений параметров, в том числе он должен уметь считать задом наперед. Использование этого генератора не должно приводить к бесконечным циклам.

def frange(): # сигнатуру придумайте сами
    # ваш код здесь

print(list(frange(start=1.0, stop=0.0, step=-0.3))) # [1.0, 0.7, 0.4, 0.1]

Итератор по лог файлам#

Предположим, что вы пишите инструмент для анализа log файлов какого-то софта. Часто за время работы программы накапливается много таких файлов. Ниже приведен список файлов в папке лог файлов некого фаервола.

access_log-20210304.bz2  access_log-20210624.bz2  access_log-20211029.bz2  access_log-20211216.bz2
access_log-20210320.bz2  access_log-20210717.bz2  access_log-20211105.bz2  access_log-20211219.bz2
access_log-20210330.bz2  access_log-20210804.bz2  access_log-20211111.bz2  access_log-20211221.bz2
access_log-20210412.bz2  access_log-20210817.bz2  access_log-20211114.bz2  access_log-20211223.bz2
access_log-20210416.bz2  access_log-20210827.bz2  access_log-20211118.bz2  access_log-20211227.bz2
access_log-20210427.bz2  access_log-20210914.bz2  access_log-20211123.bz2  access_log-20220103.bz2
access_log-20210507.bz2  access_log-20210923.bz2  access_log-20211127.bz2  access_log-20220113.bz2
access_log-20210517.bz2  access_log-20210929.bz2  access_log-20211201.bz2  access_log-20220125.bz2
access_log-20210520.bz2  access_log-20211005.bz2  access_log-20211204.bz2  access_log-20220208.bz2
access_log-20210524.bz2  access_log-20211015.bz2  access_log-20211209.bz2  access_log-20220217.bz2
access_log-20210526.bz2  access_log-20211020.bz2  access_log-20211212.bz2
access_log-20210603.bz2  access_log-20211024.bz2  access_log-20211214.bz2

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