Какие преимущества или последствия мы могли бы получить с таким кодом Python:
class some_class(parent_class):
def doOp(self, x, y):
def add(x, y):
return x + y
return add(x, y)
Я нашел это в проекте с открытым исходным кодом, делая что-то полезное внутри вложенной функции, но ничего не делая за ее пределами, кроме ее вызова. (Фактический код можно найти здесь .) Почему кто-то может его так кодировать? Есть ли какое-то преимущество или побочный эффект для написания кода внутри вложенной функции, а не во внешней нормальной функции?
python
nested-function
Хосам Али
источник
источник
Ответы:
Обычно вы делаете это для закрытия :
def make_adder(x): def add(y): return x + y return add plus5 = make_adder(5) print(plus5(12)) # prints 17
Внутренние функции могут обращаться к переменным из окружающей области (в данном случае к локальной переменной
x
). Если вы не обращаетесь ни к каким переменным из окружающей области видимости, на самом деле это обычные функции с другой областью видимости.источник
plus5 = functools.partial(operator.add, 5)
. Декораторы были бы лучшим примером для замыканий.Помимо генераторов функций, где создание внутренних функций является почти определением генератора функций, я создаю вложенные функции для улучшения читабельности. Если у меня есть крошечная функция, которая будет вызываться только внешней функцией, я встраиваю определение, поэтому вам не нужно пропускать все, чтобы определить, что делает эта функция. Я всегда могу переместить внутренний метод за пределы метода инкапсуляции, если обнаружу необходимость в повторном использовании функции позже.
Пример игрушки:
import sys def Foo(): def e(s): sys.stderr.write('ERROR: ') sys.stderr.write(s) sys.stderr.write('\n') e('I regret to inform you') e('that a shameful thing has happened.') e('Thus, I must issue this desultory message') e('across numerous lines.') Foo()
источник
Одно из потенциальных преимуществ использования внутренних методов состоит в том, что они позволяют использовать локальные переменные внешнего метода без их передачи в качестве аргументов.
def helper(feature, resultBuffer): resultBuffer.print(feature) resultBuffer.printLine() resultBuffer.flush() def save(item, resultBuffer): helper(item.description, resultBuffer) helper(item.size, resultBuffer) helper(item.type, resultBuffer)
можно записать следующим образом, что, возможно, лучше читается
def save(item, resultBuffer): def helper(feature): resultBuffer.print(feature) resultBuffer.printLine() resultBuffer.flush() helper(item.description) helper(item.size) helper(item.type)
источник
Я не могу представить себе какой-либо веской причины для такого кода.
Может быть, была причина для внутренней функции в старых версиях, как и в других Ops.
Например, это имеет немного больше смысла:
class some_class(parent_class): def doOp(self, op, x, y): def add(x, y): return x + y def sub(x,y): return x - y return locals()[op](x,y) some_class().doOp('add', 1,2)
но тогда внутренняя функция должна быть ("частным") методом класса:
class some_class(object): def _add(self, x, y): return x + y def doOp(self, x, y): return self._add(x,y)
источник
Идея локальных методов аналогична локальным переменным: не загрязнять большее пространство имен. Очевидно, что преимущества ограничены, поскольку большинство языков не предоставляют такие функции напрямую.
источник
Вы уверены, что код был именно таким? Обычная причина делать что-то подобное - создать партиал - функцию с запеченными параметрами. Вызов внешней функции возвращает вызываемый объект, которому не нужны параметры, поэтому его можно сохранить и использовать там, где невозможно передать параметры. Однако опубликованный вами код этого не сделает - он немедленно вызывает функцию и возвращает результат, а не вызываемый объект. Возможно, будет полезно опубликовать реальный код, который вы видели.
источник