Замыкания. Карринг. Декораторы.

Внутренние функции

  • Мы можем определить функцию внутри другой функции

def outer(a, b):
    def inner(c, d):
        return c + d
    return inner(a, b)
outer(4, 7)
# 11
  • Внутренние функции могут быть полезны при выполнении некоторых сложных задач более одного раза внутри другой функции. Это позволит избежать дублирования кода

  • Рассмотрим пример работы со строкой, когда внутренняя функция добавляет текст в свой аргумент:

def hello(saying):
    def inner(name):
        return f"Hello, {name}!"
    return inner(saying)

hello("Igor")
# 'Hello, Igor!'

Практика:

  • Напишите функцию, которая принимает аргумент — число. В теле функции определите внутреннюю функцию, которая принимает строку и число. Значение строки по умолчанию — "Python". Число — это количество, сколько раз должна быть продублирована строка. Верните результат работы внутренней функции во внешней функции. Протестируйте программу.

Замыкания

  • Внутренняя функция может действовать как замыкание, если возвращает функцию

  • Замыкание — это функция, которая находится внутри другой функции и ссылается на переменные, объявленные в теле внешней функции

  • Применение замыканий позволяет создавать функции с доступом к переменным, находящимся вне их области видимости и запоминать значения переменных

  • Внутри внешней функции мы можем создавать переменные и изменять их во внутренних функциях

  • Для этого используется ключевое слово nonlocal

  • Пример использования замыкания и ключевого слова nonlocal для генерации ID:

Практика:

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

Пример работы программы:

  1. Создайте функцию для генерации паролей. Функция должна принимать символы, из которых будет генерироваться пароль (установите для этого значение по умолчанию), и длину пароля. При каждом вызове она должна возвращать новый случайный пароль. Используйте замыкание и модули random и string

Пример работы программы:

Карринг

  • Карринг (currying) — это техника в функциональном программировании, при которой функция, принимающая несколько аргументов, преобразуется в последовательность функций, каждая из которых принимает по одному аргументу.

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

  • Ещё один пример:

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

Практика:

  • Создайте функцию умножения двух чисел. Используйте карринг

Декораторы

  • Иногда нам нужно модифицировать существующую функцию, не меняя при этом исходный код

  • Декоратор — это функция, которая принимает одну функцию в качестве аргумента и возвращает другую функцию. По сути это "обертка" для нашей функции, которая добавляет ей функционал

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

  • Для того чтобы сделать декоратор универсальным, можно сразу указать все возможные аргументы (позиционные и ключевые) таким образом:

  • В Python есть "синтаксический сахар" — более удобная форма записи для декораторов:

Пример — декоратор, измеряющий время работы функций:

Практика:

  1. Напишите функцию конкатенации двух строк. Измерьте время её работы при помощи декоратора test_time

  2. Определите декоратор test, который выводит строку start при вызове функции и строку end, когда функция завершает свою работу. Дополнительно: добавьте вывод имени запускаемой функции (используйте метод func.__name__)

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

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

Last updated