Newer
Older
# Определение функций высшего порядка. Замыкания. Декораторы.
1. Написать функцию `combine`, принимающую два аргумента: функции f и g, и возвращающая новую
функцию f * g
```Python
x = 42
f = lambda x: x // 7
g = lambda x: x ** 2
assert g(f(x)) == combine(f, g)(x)
```
2. Написать функцию `curry`, которая в качестве аргумента принимает функцию с неопределенным количеством
**позиционных** (не меньше одного)
аргументов и возвращает функцию одного аргумента, которая возвращает функцию от остальных аргументов:
```Python
f = lambda x, y, z: x + y + z
assert curry(f)(1)(2, 3) == f(1, 2, 3)
```
3. Написать декоратор `n_times`, в случае декорирования функции которым, она будет применена к собственному
результату `n` раз (`n` - аргумент декоратора).
```Python
@n_times(1)
def sum_2(x):
return x + 2
assert sum_2(4) == 6
@n_times(10)
def sum_2(x):
return x + 2
assert sum_2(4) == 24
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
4. Написать декоратор `series` с аргемнтом `initial` (условно, значение члена ряда с индексом 0),
который оборачивает функцию с аргументами
`i, prev` и превращает ее в функцию вычисления ряда, заданного рекуррентно:
```Python
@series(1)
def factorial(i, prev):
return i * prev
assert factorial(4) == [1, 2, 6, 24]
```
5. Написать функцию `mean_closure`, котороя возвращает функцию, которая при каждом обращении возвращает
среднее от всех аргументов, которые ей были переданы. (Если возникает ошибка вычислений с плавающей точкой
и оператор `==` возвращает False, то можно использовать `math.isclose`)
```Python
mean = mean_closure()
assert mean(1) == 1.0
assert mean(3) == 2.0
assert mean(2) == 2.0
```
6. Написать декоратор `tag`, который оборачивает функцию произвольных аргументов, возвращающую строковое значение, обрамляя это значение
выбранным html-тегом (параметр декоратора):
```Python
@tag('html')
@tag('p')
def greet(s):
return f"Hello, {s}!"
assert greet("World") == "<html><p>Hello, World!</p></html>"
```
7. Написать функцию then, которая в качестве аргумента принимает две функции f и g и возвращает новую функцию
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
```Python
x = 42
f = lambda x: x // 7
g = lambda x: x ** 2
assert f(g(x)) == then(f, g)(x)
```
8. Написать декоратор `http`, который оборачивает функцию произвольных аргементов, возвращающую строковое значение, который возвращает
кортеж (строковое значение, 200), если строка непуста, иначе ('Error: not found', 404)
```Python
@http
def dummy(s):
return s
assert dummy("Response") == ("Response", 200)
assert dummy("") == ("Error: not found", 404)
assert dummy("Error: not found") == ("Error: not found", 200)
```
9. Написать замыкание `counter_clojure`, возвращает функцию, которая при каждом обращении подсчитывает частоту всех символов в
переданных аргументах:
```Python
counter = counter_clojure()
assert counter("Привет") == {"П": 1, "р": 1, "и": 1, "в": 1, "e": 1, "т": 1}
assert counter("мир") == {"П": 1, "р": 2, "и": 2, "в": 1, "e": 1, "т": 1, "м": 1}
```
10. Написать декоратор `logger`, который принимает произвольную функцию, и возвращает функцию, которая до выполнения
выводит все свои аргументы (именованные и неименованные в stderr), а после выполнения выводит результат в stderr.
Все значения должны быть оценены как строковые
```Python
@logger
greet(greeting, name):
return f"{greeting}, {name}!"
assert greet("Hello", name="Alice") == "Hello, Alice!"
# В stderr должно быть выведено две строчки
# Arguments: (Hello, name=Alice)
# Result: Hello, Alice
```