Skip to content
Snippets Groups Projects
functions.md 4.89 KiB
Newer Older
GulyaevSA's avatar
GulyaevSA committed
# Определение функций высшего порядка. Замыкания. Декораторы.
GulyaevSA's avatar
GulyaevSA committed

GulyaevSA's avatar
GulyaevSA committed
1. Написать функцию `combine`, принимающую два аргумента: функции f и g, и возвращающая новую 
GulyaevSA's avatar
GulyaevSA committed
функцию 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
GulyaevSA's avatar
GulyaevSA committed
```
GulyaevSA's avatar
GulyaevSA committed

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 и возвращает новую функцию
GulyaevSA's avatar
GulyaevSA committed
`g * f` (см. задание 1)
GulyaevSA's avatar
GulyaevSA committed

```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
```