Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

С какой целью нужно объявление функции внутри функции?

#python #функции


В питоновском коде несколько раз встречал подобные конструкции:

def spam():
...
    def eggs():
    ...


Т.е. мы объявляем функцию eggs() внутри функции spam(). С какой целью нужны такие
конструкции? Единственное, что приходит в голову -- это области видимости, т.к. функция
eggs() не будет видна за пределами функции spam().
    


Ответы

Ответ 1



Причина: Область видимости. Возможно, вы для упрощения кода внутри функции захотели его обернуть в функцию, но в то же время, не хотите чтобы внутренние вспомогательные функции торчали наружу. Например у вас есть функция, которая принимает в параметры списки, делает над ними операции и возвращает результат. Код внутри повторяется и нужно что-то с этим делать: def pow_and_sum(items_1, items_2, items_3) -> int: items_1 = map(int, items_1) items_2 = map(int, items_2) items_3 = map(int, items_3) items_1 = map(lambda x: pow(x, 2), items_1) items_2 = map(lambda x: pow(x, 2), items_2) items_3 = map(lambda x: pow(x, 2), items_3) return sum(items_1) + sum(items_2) + sum(items_3) Обычное решение повторяющего кода -- обернуть его в функцию, а т.к. та функция очень специфична и мы не хотим чтобы она была видна глобально, создаем ее в локальной видимости: def pow_and_sum(items_1, items_2, items_3) -> int: def do(items): items = map(int, items) items = map(lambda x: pow(x, 2), items) return sum(map(int, items)) return do(items_1) + do(items_2) + do(items_3) print(pow_and_sum('123', [1, 2], ['1', 4])) # 36 А также это используется в: Замыкания (closure) # multiplier возвращает функцию умножения на n def multiplier(n): def mul(k): return n * k return mul # mul3 - функция, умножающая на 3 mul3 = multiplier(3) print(mul3(3), mul3(5)) # 9 15 Карринг (currying) def my_sum(x, y, z): return x + y + z def foo(x): def a(y): def b(z): return my_sum(x, y, z) return b return a print(foo(1)(2)(3)) # 6 print(foo("1")("2")("3")) # 123 Декораторы (decorator) def makebold(fn): def wrapped(*args, **kwargs): return "" + fn(*args, **kwargs) + "" return wrapped def makeitalic(fn): def wrapped(*args, **kwargs): return "" + fn(*args, **kwargs) + "" return wrapped def upper(fn): def wrapped(*args, **kwargs): return fn(*args, **kwargs).upper() return wrapped @makebold @makeitalic @upper def hello(text): return text print(hello('Hello World!')) # HELLO WORLD!

Ответ 2



Довольно немало функций которые получают параметром другую функцию. Например таким образом удобно оперировать с коллекциями. Например, не привязываясь к языку, можно написать coollection.where(myFunc) и результатом будет коллекция отфильтрованная по условию в myFunc. Функция может быть колбеком, это удобно если у нас есть замыкания, например типичный пример использования - передать в какой нибудь объект функцию которая как то модифицирует поля текущего объекта из которого мы ее передаем. Например: var progress = 0; new obj((increment)->{progress += increment}).start(); В данном случае у нас создается новый объект которому мы передаем колбек для увеличения счетчика прогресса и запускаем этот объект методом start(); Ну и иногда да, просто удобно не захламлять общую область видимости функцией котрая нужна только в одном месте. А, еще например в js такое определение позволяет создавать объекты с методами.

Комментариев нет:

Отправить комментарий