Вложенная функция в Python

какую пользу или последствия мы могли бы получить с кодом Python, как это:

class some_class(parent_class):
    def doOp(self, x, y):
        def add(x, y):
            return x + y
        return add(x, y)

Я нашел это в проекте с открытым исходным кодом, делая что-то полезное внутри вложенной функции, но ничего не делая вне ее, кроме вызова. (Фактический код можно найти здесь. Почему кто-то может его так закодировать? Есть ли какая-то польза или побочный эффект для написания кода внутри вложенной функции, а не во внешней, нормальной функции?

6 ответов


обычно вы делаете это, чтобы сделать закрытие:

def make_adder(x):
    def add(y):
        return x + y
    return add

plus5 = make_adder(5)
print(plus5(12))  # prints 17

внутренние функции могут обращаться к переменным из заключительной области (в этом случае локальная переменная x). Если вы не обращаетесь к переменным из заключительной области, они действительно являются обычными функциями с другой областью.


помимо функциональных генераторов, где внутреннее создание функций-это почти определение функционального генератора, причина, по которой я создаю вложенные функции, - это улучшение читаемости. Если у меня есть крошечная функция, которая будет вызываться только внешней функцией, тогда я вставляю определение, чтобы вам не пришлось пропускать, чтобы определить, что делает эта функция. Я всегда могу переместить внутренний метод за пределы метода инкапсуляции, если мне понадобится повторно использовать функцию позже дата.

игрушки например:

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)

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


вы уверены, что код был именно такой? Обычная причина для чего - то подобного-создание частичной функции с запеченными параметрами. Вызов внешней функции возвращает вызываемый объект, который не нуждается в параметрах, и поэтому может быть сохранен и использован где-то невозможно передать параметры. Однако код, который вы разместили, этого не сделает - он немедленно вызывает функцию и возвращает результат, а не вызываемый. Может быть полезно опубликовать фактический код вы видели.