В python, когда вы передаете внутренне определенные функции в другие функции, как он сохраняет переменные? - PullRequest
9 голосов
/ 16 августа 2011

Например, почему это работает?

def func1(func1var):
    def innerfunc(innerfuncvar):
        if func1var == 1:
             print innerfuncvar
        else:
             print 5
    func2(innerfunc)


def func2(function):
     function(9)

Когда innerfunc вызывается в func2, как он узнает значения func1var?

Ответы [ 3 ]

7 голосов
/ 16 августа 2011

Вы создали замыкание . По сути, думайте об этом так, с точки зрения внутренней функции:

func1var = whatever

def func2(function):
    function(9)

def innerfunc(innerfuncvar):
    if func1var = 1:
         print innerfuncvar
    else:
         print 5

func2(innerfunc)

Не имеет значения, находится ли func1var во внешней или глобальной области видимости - он просто ищет его в каждой области за пределами, начиная с собственной локальной области. Это похоже на обращение к глобальной переменной модуля внутри класса или функции в этом модуле.

6 голосов
/ 16 августа 2011

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

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

def make_adder(increment):
    def adder(number):
        return number + increment
    adder.__name__ = "adder(%s)" % increment
    return adder

Эта функция является функцией, которая создает функцию, которая добавляет к ней указанное значение.Например:

add1 = make_adder(1)
add5 = make_adder(5)

print add1(10)   # 11
print add5(10)   # 15

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

2 голосов
/ 16 августа 2011

Каждый раз, когда вы вызываете func1(func1var), Python фактически создает новую функцию innerfunc(). Поскольку func1var идеально определяется при создании innerfunc(), код новой функции innerfunc() содержит правильное значение func1var.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...