'''Тема урока: функции высшего порядка
Функции высшего порядка
Самописные функции map(), filter(), reduce()
Аннотация. Урок посвящен функциям высшего порядка.

Функции высшего порядка
Как уже сказано, функции, которые принимают или/и возвращают другие функции, называются функциями высшего порядка.

Давайте реализуем простейшую функцию высшего порядка:

def high_order_function(func):     # функция высшего порядка, так как принимает функцию
    return func(3)


def double(x):                     # обычная функция = функция первого порядка
    return 2*x


def add_one(x):                    # обычная функция = функция первого порядка
    return x + 1
Здесь функция high_order_function() принимает другую функцию на входе и возвращает результат её вызова с аргументом,
 равным 33.

Приведенный ниже код:

print(high_order_function(double))
print(high_order_function(add_one))
выводит:

6
4
Функции первого порядка принимают и возвращают "обычные" значения, не функции, функции высшего порядка принимают или/и
 возвращают другие функции.

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

map();
filter();
reduce().
В языке Python эти функции уже реализованы, однако для лучшего понимания их работы мы сначала напишем свои версии этих
функций, и уже после этого поговорим о встроенных реализациях.

Функции высшего порядка map(), filter() и reduce() довольно широко распространены в функциональном программировании и
часто применяются программистами.

Функция map()
При работе со списками часто требуется применить одно и то же преобразование к каждому элементу. Можно написать цикл,
содержащий нужное преобразование.

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

def f(x):
    return x**2     # тело функции, которая преобразует аргумент x


old_list = [1, 2, 4, 9, 10, 25]
new_list = []
for item in old_list:
    new_item = f(item)
    new_list.append(new_item)

print(old_list)
print(new_list)
Результатом работы такого кода будет:

[1, 2, 4, 9, 10, 25]
[1, 4, 16, 81, 100, 625]
Несложно понять, что цикл будет выглядеть одинаково практически во всех случаях. Меняться будет только преобразование,
 то есть применяемая функция f(). Так почему бы не обобщить код, чтобы функция была параметром? Так и сделаем:

def map(function, items):
    result = []
    for item in items:
        new_item = function(item)
        result.append(new_item)
    return result
Теперь мы можем совершать преобразования, используя функцию высшего порядка map().

Приведенный ниже код:

def square(x):
    return x**2


def cube(x):
    return x**3


numbers = [1, 2, -3, 4, -5, 6, -9, 0]

strings = map(str, numbers)        # используем в качестве преобразователя - функцию str
abs_numbers = map(abs, numbers)    # используем в качестве преобразователя - функцию abs

squares = map(square, numbers)     # используем в качестве преобразователя - функцию square
cubes = map(cube, numbers)         # используем в качестве преобразователя - функцию cube
выводит:

['1', '2', '-3', '4', '-5', '6', '-9', '0']
[1, 2, 3, 4, 5, 6, 9, 0]
[1, 4, 9, 16, 25, 36, 81, 0]
[1, 8, -27, 64, -125, 216, -729, 0]
Функция называется "map" то есть "отобразить". Название пришло из математики, где так называется функция, отображающая
одно множество значений в другое путём преобразования всех элементов с помощью некой трансформации.

Реализованную нами функцию map() можно использовать как альтернативную возможность для преобразования типов элементов
любого списка. Раньше мы решали такую задачу с помощью списочных выражений. Теперь можем использовать и функцию map().

Приведенный ниже код, при условии, что функция map() определена как указано выше:

strings = ['10', '12', '-4', '-9', '0', '1', '23', '100', '99']

numbers1 = [int(str) for str in strings]   # используем списочное выражение для преобразования
numbers2 = map(int, strings)               # используем функцию map() для преобразования

print(numbers1)
print(numbers2)
выводит:

[10, 12, -4, -9, 0, 1, 23, 100, 99]
[10, 12, -4, -9, 0, 1, 23, 100, 99]
Цепочки преобразований
Мы также можем строить цепочки преобразований, несколько раз вызывая функцию map().

Приведенный ниже код, при условии, что функция map() определена как указано выше:

numbers = ['-1', '20', '3', '-94', '65', '6', '-970', '8']

new_numbers = map(abs, map(int, numbers))

print(new_numbers)
выводит:

[1, 20, 3, 94, 65, 6, 970, 8]
То есть, сначала мы преобразуем список строк в список чисел с помощью кода map(int, numbers), получая список
[-1, 20, 3, -94, 65, 6, -970, 8]. Далее с помощью еще одного вызова функции map() трансформируем полученный список в
 список [1, 20, 3, 94, 65, 6, 970, 8].

Функция filter()
Другая популярная задача при работе со списками: отобрать часть элементов списка по определенному критерию. Функция
высшего порядка для решения такой задачи называется filter().

   Функция-критерий, которая возвращает значение True или False , называется предикатом.

Реализация такой функции может выглядеть так:

def filter(function, items):
    result = []
    for item in items:
        if function(item):
            result.append(item)  # добавляем элемент item если функция function вернула значение True
    return result
Наша функция filter() применяет предикат function к каждому элементу и добавляет в итоговый список только те элементы,
для которых предикат вернул True.

Например, чтобы из исходного списка чисел получить список с элементами, большими 1010, можно написать такой код:

def is_greater10(num):   # функция возвращает значение True если число больше 10 и False в противном случае
    return num > 10


numbers = [12, 2, -30, 48, 51, -60, 19, 10, 13]

large_numbers = filter(is_greater10, numbers)   #  список large_numbers содержит элементы, большие 10

print(large_numbers)
Этот код, при условии, что функция filter() определена как указано выше выводит:

[12, 48, 51, 19, 13]
Рассмотрим еще пару примеров применения реализованной функции filter().

Приведенный ниже код, при условии, что функция filter() определена как указано выше:

def is_odd(num):
    return num % 2


def is_word_long(word):
    return len(word) > 6


numbers = list(range(15))
words = ['В', 'новом', 'списке', 'останутся', 'только', 'длинные', 'слова']

odd_numbers = filter(is_odd, numbers)
large_words = filter(is_word_long, words)

print(odd_numbers)
print(large_words)
выводит:

[1, 3, 5, 7, 9, 11, 13]
['останутся', 'длинные']
Функция reduce()
Реализованные нами функции map() и filter() работали с отдельными элементами списка независимо. Но встречаются циклы
с агрегацией результата — формированием одного результирующего значения при комбинации элементов с использованием
аргумента-аккумулятора.

Типичные примеры агрегации — сумма всех элементов списка или их произведение.

Приведенный ниже код:

numbers = [1, 2, 3, 4, 5]

total = 0
product = 1

for num in numbers:
    total += num
    product *= num

print(total)
print(product)
вычисляет сумму и произведение элементов списка и выводит:

15
120
С точки зрения математики сумма 1 + 2 + 3 + 4 + 51+2+3+4+5 может быть выражена как:

(((((0 + 1) + 2) + 3) + 4) + 5).
(((((0+1)+2)+3)+4)+5).
Ноль здесь тот самый аккумулятор, точнее его начальное значение. Он не добавляет к сумме ничего, поэтому может служить
отправной точкой. А еще будет результатом, если входной список пуст.

Несложно понять, что этот цикл будет выглядеть одинаково практически во всех случаях. Меняться будет только начальное
 значение аккумулятора (00 для суммы, 11 для произведения и т.д.) и операция, которая комбинирует элемент и
 аккумулятор. Так почему бы не обобщить этот код? Так и сделаем:

def reduce(operation, items, initial_value):
    acc = initial_value
    for item in items:
        acc = operation(acc, item)
    return acc
Приведенный ниже код, при условии, что функция reduce() определена как указано выше:

def add(x, y):
    return x+y


def mult(x, y):
    return x*y


numbers = [1, 2, 3, 4, 5]

total = reduce(add, numbers, 0)
product = reduce(mult, numbers, 1)

print(total)
print(product)
выводит:

15
120
Примечания
Примечание 1. Мы с вами реализовали три функции:

map(): преобразование элементов списка;
filter(): фильтрация элементов списка;
reduce(): агрегация элементов списка.
Каждая функция имеет меньшую мощность, чем цикл for. Цикл for позволяет гибко управлять процессом итерации,
мы можем использовать даже команды break и continue. Возникает резонный вопрос: зачем нужны отдельные функции,
 когда можно обойтись циклом?

Во-первых, такие функции — часть функционального подхода.

Во-вторых, каждая такая функция делает единственную работу, что значительно упрощает рассуждение о коде, его чтение
 и написание. Взглянув на имя функции можно понять, что filter() отфильтрует, а map() — преобразует элементы. Более
  того, по построению функция filter() не меняет элементы, а лишь отбрасывает их часть. А функция map() меняет
  значение элементов, но не меняет их количество и позиции.

Примечание 2. В математике определенная нами функция reduce() называется левая свёртка (left fold), по сути мы
сворачиваем список в одно значение, начиная слева. Существует ещё и правая свёртка (right fold). В большинстве
случаев обе свёртки дают одинаковый результат, если применяемая операция ассоциативна.'''


'''Функция высшего порядка это'''

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


# words = ['abba', 'qwerty', 'python', 'a', 'deed', 'nun', 'level', 'deified', 'bbbbb', 'mother', 'surface', 'sister']
#
# words_len = map(len, words)
# print(max(words_len))
7#

# def predicate(word):
#     return word == word[::-1]
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
#
#
# words = ['abba', 'qwerty', 'python', 'a', 'deed', 'nun', 'level', 'language', 'deified', 'bbbbb', 'mother', 'sister', 'surface', '1234321']
# filtered = filter(predicate, words)
# print(len(filtered))
#  8#


# numbers = [-2, 45, 45, -7, -45, 37, -42, 27, -58, -58, -12, -27, -49, -27, -56, 4, -99, -11, 86]
# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
# var1 = max(numbers, key=abs)
# var2 = min(map(abs, numbers))
#
# print(var1 + var2) #-97

'''Напишите программу, которая с помощью функции map() округляет все элементы списка numbers до 2 десятичных 
знаков, а затем выводит их, каждый на отдельной строке.'''

# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
# def roundx(num):
#     return round(num, 2)
#
# numbers=[3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.12013, 23.22222, 90.09873, 45.45, 314.1528, 2.71828, 1.41546]
# print(*map(roundx, numbers), sep='\n')


# from decimal import Decimal
# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
#
# numbers = [3.56773, 5.57668, 4.00914, 56.24241, 9.01344, 32.12013, 23.22222, 90.09873, 45.45, 314.1528, 2.71828, 1.41546]
#
# numbers1 = map(Decimal,numbers)
# for i in numbers1:
#     print(i.quantize(Decimal('1.00')))


'''Напишите программу, которая с помощью функций filter() и map() отбирает из заданного списка numbers трёхзначные
 числа, дающие при делении на 5 остаток 2, и выводит их кубы, каждый в отдельной строке.

Примечание. Остаток 2 при делении на 5 должно давать само число, а не его куб.'''


# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
# def is_3zn(num):
#     return 99 < num < 1000 and num % 5 == 2
# def cubes(num):
#     return num ** 3
# numbers = [1014, 1321, 675, 1215, 56, 1386, 1385, 431, 1058, 486, 1434, 696, 1016, 1084, 424, 1189, 475, 95, 1434, 1462, 815, 776, 657, 1225, 912, 537, 1478, 1176, 544, 488, 668, 944, 207, 266, 1309, 1027, 257, 1374, 1289, 1155, 230, 866, 708, 144, 1434, 1163, 345, 394, 560, 338, 232, 182, 1438, 1127, 928, 1309, 98, 530, 1013, 898, 669, 105, 130, 1363, 947, 72, 1278, 166, 904, 349, 831, 1207, 1496, 370, 725, 926, 175, 959, 1282, 336, 1268, 351, 1439, 186, 273, 1008, 231, 138, 142, 433, 456, 1268, 1018, 1274, 387, 120, 340, 963, 832, 1127]
# print(*map(cubes, filter(is_3zn, numbers)), sep='\n')

# numbers = [1014, 1321, 675, 1215, 56, 1386, 1385, 431, 1058, 486, 1434, 696, 1016, 1084, 424, 1189, 475, 95, 1434, 1462,
#            815, 776, 657, 1225, 912, 537, 1478, 1176, 544, 488, 668, 944, 207, 266, 1309, 1027, 257, 1374, 1289, 1155,
#            230, 866, 708, 144, 1434, 1163, 345, 394, 560, 338, 232, 182, 1438, 1127, 928, 1309, 98, 530, 1013, 898, 669,
#            105, 130, 1363, 947, 72, 1278, 166, 904, 349, 831, 1207, 1496, 370, 725, 926, 175, 959, 1282, 336, 1268,
#            351, 1439, 186, 273, 1008, 231, 138, 142, 433, 456, 1268, 1018, 1274, 387, 120, 340, 963, 832, 1127]
# print(*map(lambda x: x**3, filter(lambda x: x%5 == 2 and x in range(100,1000),numbers)), sep='\n')

#
# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
#
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
# def one(x):
#     return x % 5 == 2 and len(str(x)) == 3
# def two(x):
#     return x ** 3
#
# numbers = [1014, 1321, 675, 1215, 56, 1386, 1385, 431, 1058, 486, 1434, 696, 1016, 1084, 424, 1189, 475, 95, 1434, 1462, 815, 776, 657, 1225, 912, 537, 1478, 1176, 544, 488, 668, 944, 207, 266, 1309, 1027, 257, 1374, 1289, 1155, 230, 866, 708, 144, 1434, 1163, 345, 394, 560, 338, 232, 182, 1438, 1127, 928, 1309, 98, 530, 1013, 898, 669, 105, 130, 1363, 947, 72, 1278, 166, 904, 349, 831, 1207, 1496, 370, 725, 926, 175, 959, 1282, 336, 1268, 351, 1439, 186, 273, 1008, 231, 138, 142, 433, 456, 1268, 1018, 1274, 387, 120, 340, 963, 832, 1127]
# numbers1 = map(two,filter(one,numbers))
# print(*numbers1,sep = '\n')


'''Напишите программу для вычисления и вывода суммы квадратов элементов списка numbers. Решите задачу двумя способами: 
с помощью функции reduce(), и с помощью функций map() и sum().'''

# def reduce(operation, items, initial_value):
#     acc = initial_value
#     for item in items:
#         acc = operation(acc, item)
#     return acc
# def square(acc, num):
#     return acc + num ** 2
# numbers = [97, 42, 9, 32, 3, 45, 31, 77, -1, 11, -2, 75, 5, 51, 34, 28, 46, 1, -8, 84, 16, 51, 90, 56, 65, 90, 23, 35, 11, -10, 70, 90, 90, 12, 96, 58, -8, -4, 91, 76, 94, 60, 72, 43, 4, -6, -5, 51, 58, 60, 30, 38, 67, 62, 36, 72, 34, 82, 62, -1, 60, 82, 87, 81, -7, 57, 26, 36, 17, 43, 80, 40, 75, 94, 91, 64, 38, 72, 29, 84, 38, 35, 7, 54, 31, 95, 78, 27, 82, 1, 64, 94, 31, 29, -8, 98, 24, 61, 7, 73]
# print(reduce(square, numbers, 0))



# def reduce(operation, items, initial_value):
#     acc = initial_value
#     for item in items:
#         acc = operation(acc, item)
#     return acc
# def add(x, y):
#     return x + y**2
#
# numbers = [97, 42, 9, 32, 3, 45, 31, 77, -1, 11, -2, 75, 5, 51, 34, 28, 46, 1, -8, 84, 16, 51, 90, 56, 65, 90, 23, 35, 11, -10, 70, 90, 90, 12, 96, 58, -8, -4, 91, 76, 94, 60, 72, 43, 4, -6, -5, 51, 58, 60, 30, 38, 67, 62, 36, 72, 34, 82, 62, -1, 60, 82, 87, 81, -7, 57, 26, 36, 17, 43, 80, 40, 75, 94, 91, 64, 38, 72, 29, 84, 38, 35, 7, 54, 31, 95, 78, 27, 82, 1, 64, 94, 31, 29, -8, 98, 24, 61, 7, 73]
#
# print(reduce(add, numbers, 0))


# def reduce(operation, items, initial_value):
#     acc = initial_value
#     for item in items:
#         acc = operation(acc, item)
#     return acc
#
#
# numbers = [97, 42, 9, 32, 3, 45, 31, 77, -1, 11, -2, 75, 5, 51, 34, 28, 46, 1, -8, 84, 16, 51, 90, 56, 65, 90, 23, 35, 11, -10, 70, 90, 90, 12, 96, 58, -8, -4, 91, 76, 94, 60, 72, 43, 4, -6, -5, 51, 58, 60, 30, 38, 67, 62, 36, 72, 34, 82, 62, -1, 60, 82, 87, 81, -7, 57, 26, 36, 17, 43, 80, 40, 75, 94, 91, 64, 38, 72, 29, 84, 38, 35, 7, 54, 31, 95, 78, 27, 82, 1, 64, 94, 31, 29, -8, 98, 24, 61, 7, 73]
#
# print(reduce(lambda acc, x: acc + x*x, numbers, 0))

'''Напишите программу для вычисления и вывода суммы квадратов двузначных чисел, которые делятся на 7 без остатка.

Примечание 1. При решении задачи используйте функции filter(), map() и sum().

Примечание 2. На 77 должно делиться исходное двузначное число, а не его квадрат.

Примечание 3. Не забывайте про отрицательные двузначные числа.'''
# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
# def square(x):
#     return x ** 2
# def is_2zn(x):
#     return 9 < abs(x) < 100 and abs(x) % 7 == 0
# numbers = [77, 293, 28, 242, 213, 285, 71, 286, 144, 276, 61, 298, 280, 214, 156, 227, 228, 51, -4, 202, 58, 99, 270, 219, 94, 253, 53, 235, 9, 158, 49, 183, 166, 205, 183, 266, 180, 6, 279, 200, 208, 231, 178, 201, 260, -35, 152, 115, 79, 284, 181, 92, 286, 98, 271, 259, 258, 196, -8, 43, 2, 128, 143, 43, 297, 229, 60, 254, -9, 5, 187, 220, -8, 111, 285, 5, 263, 187, 192, -9, 268, -9, 23, 71, 135, 7, -161, 65, 135, 29, 148, 242, 33, 35, 211, 5, 161, 46, 159, 23, 169, 23, 172, 184, -7, 228, 129, 274, 73, 197, 272, 54, 278, 26, 280, 13, 171, 2, 79, -2, 183, 10, 236, 276, 4, 29, -10, 41, 269, 94, 279, 129, 39, 92, -63, 263, 219, 57, 18, 236, 291, 234, 10, 250, 0, 64, 172, 216, 30, 15, 229, 205, 123, -105]
# print(sum(map(square, filter(is_2zn, numbers))))


# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
#
# numbers = [77, 293, 28, 242, 213, 285, 71, 286, 144, 276, 61, 298, 280, 214, 156, 227, 228, 51, -4, 202, 58, 99, 270, 219, 94, 253, 53, 235, 9, 158, 49, 183, 166, 205, 183, 266, 180, 6, 279, 200, 208, 231, 178, 201, 260, 152, 115, 79, 284, 181, 92, 286, 98, 271, 259, 258, 196, -8, 43, 2, 128, 143, 43, 297, 229, 60, 254, -9, 5, 187, 220, -8, 111, 285, 5, 263, 187, 192, -9, 268, -9, 23, 71, 135, 7, 65, 135, 29, 148, 242, 33, 35, 211, 5, 161, 46, 159, 23, 169, 23, 172, 184, -7, 228, 129, 274, 73, 197, 272, 54, 278, 26, 280, 13, 171, 2, 79, -2, 183, 10, 236, 276, 4, 29, -10, 41, 269, 94, 279, 129, 39, 92, 263, 219, 57, 18, 236, 291, 234, 10, 250, 0, 64, 172, 216, 30, 15, 229, 205, 123]
# print(sum(map(lambda x: x**2, filter(lambda x: 100 > abs(x) > 9 and x % 7 == 0, numbers))))


# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
#
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
#
#
# def num2(num):
#     return 1 <= abs(num)//10 < 10
#
#
# def square(num):
#     return num**2
#
#
# def div7(num):
#     return num%7==0
#
#
# numbers = [77, 293, 28, 242, 213, 285, 71, 286, 144, 276, 61, 298, 280, 214, 156, 227, 228, 51, -4, 202, 58, 99, 270, 219, 94, 253, 53, 235, 9, 158, 49, 183, 166, 205, 183, 266, 180, 6, 279, 200, 208, 231, 178, 201, 260, -35, 152, 115, 79, 284, 181, 92, 286, 98, 271, 259, 258, 196, -8, 43, 2, 128, 143, 43, 297, 229, 60, 254, -9, 5, 187, 220, -8, 111, 285, 5, 263, 187, 192, -9, 268, -9, 23, 71, 135, 7, -161, 65, 135, 29, 148, 242, 33, 35, 211, 5, 161, 46, 159, 23, 169, 23, 172, 184, -7, 228, 129, 274, 73, 197, 272, 54, 278, 26, 280, 13, 171, 2, 79, -2, 183, 10, 236, 276, 4, 29, -10, 41, 269, 94, 279, 129, 39, 92, -63, 263, 219, 57, 18, 236, 291, 234, 10, 250, 0, 64, 172, 216, 30, 15, 229, 205, 123, -105]
#
# numbers=filter(num2, numbers)
# numbers=filter(div7, numbers)
# numbers=map(square, numbers)
# print(sum(numbers))

# def map(function, items):
#     result = []
#     for item in items:
#         result.append(function(item))
#     return result
#
#
# def filter(function, items):
#     result = []
#     for item in items:
#         if function(item):
#             result.append(item)
#     return result
#
#
# numbers = [77, 293, 28, 242, 213, 285, 71, 286, 144, 276, 61, 298, 280, 214, 156, 227, 228, 51, -4, 202, 58, 99, 270, 219, 94, 253, 53, 235, 9, 158, 49, 183, 166, 205, 183, 266, 180, 6, 279, 200, 208, 231, 178, 201, 260, -35, 152, 115, 79, 284, 181, 92, 286, 98, 271, 259, 258, 196, -8, 43, 2, 128, 143, 43, 297, 229, 60, 254, -9, 5, 187, 220, -8, 111, 285, 5, 263, 187, 192, -9, 268, -9, 23, 71, 135, 7, -161, 65, 135, 29, 148, 242, 33, 35, 211, 5, 161, 46, 159, 23, 169, 23, 172, 184, -7, 228, 129, 274, 73, 197, 272, 54, 278, 26, 280, 13, 171, 2, 79, -2, 183, 10, 236, 276, 4, 29, -10, 41, 269, 94, 279, 129, 39, 92, -63, 263, 219, 57, 18, 236, 291, 234, 10, 250, 0, 64, 172, 216, 30, 15, 229, 205, 123, -105]
#
# print(sum(map(lambda x: x**2, filter(lambda x: x%7==0 and len(str(x))==2, map(abs, numbers)))))

'''Напишите функцию func_apply(), принимающую на вход функцию и список значений и возвращающую список, в котором 
каждое значение будет результатом применения переданной функции к переданному списку.

Примечание 1. Приведенный ниже код, при условии, что функция func_apply() написана правильно

def add3(x):
    return x + 3


def mul7(x):
    return x * 7


print(func_apply(mul7, [1, 2, 3, 4, 5, 6]))
print(func_apply(add3, [1, 2, 3, 4, 5, 6]))
print(func_apply(str, [1, 2, 3, 4, 5, 6]))
должен выводить:

[7, 14, 21, 28, 35, 42]
[4, 5, 6, 7, 8, 9]
['1', '2', '3', '4', '5', '6']
Примечание 2. Вызывать функцию func_apply() не нужно, требуется только реализовать ее.'''

# def func_apply(func,elem):
#
#     return map(func,elem)
#
# def add3(x):
#     return x + 3
#
#
# def mul7(x):
#     return x * 7
#
# def map(function, items):
#     result = []
#     for item in items:
#         new_item = function(item)
#         result.append(new_item)
#     return result
#
#
#
# print(func_apply(mul7, [1, 2, 3, 4, 5, 6]))
# print(func_apply(add3, [1, 2, 3, 4, 5, 6]))
# print(func_apply(str, [1, 2, 3, 4, 5, 6]))


# def func_apply(func, ar):
#     return list(map(func, ar))


# func_apply = lambda func, lst: [func(i) for i in lst]