Можно ли объяснить закрытия (поскольку они касаются Python)?

Вот самый маленький фрагмент кода для проверки готовности DOM, который работает во всех браузерах (даже IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

См. этот ответ .

78
задан Honest Abe 23 February 2014 в 22:43
поделиться

7 ответов

Закрытие на закрытиях

Объекты являются данными с присоединенными методами, закрытия являются функциями с присоединенными данными.

def make_counter():
    i = 0
    def counter(): # counter() is a closure
        nonlocal i
        i += 1
        return i
    return counter

c1 = make_counter()
c2 = make_counter()

print (c1(), c1(), c2(), c2())
# -> 1 2 1 2
88
ответ дан jfs 24 November 2019 в 10:32
поделиться

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

>>> def makeConstantAdder(x):
...     constant = x
...     def adder(y):
...         return y + constant
...     return adder
... 
>>> f = makeConstantAdder(12)
>>> f(3)
15
>>> g = makeConstantAdder(4)
>>> g(3)
7

Примечание, которые 12 и 4 "исчезли" внутри f и g, соответственно, эта функция, - то, что делает f и g надлежащие закрытия.

44
ответ дан Anders Eurenius 24 November 2019 в 10:32
поделиться

Мне нравится это грубое, сжатое определение :

функция А, которая может относиться к средам, которые больше не активны.

я добавил бы

, закрытие А позволяет Вам связывать переменные в функцию , не передавая их как параметры .

Декораторы, которые принимают параметры, являются общим использованием для закрытий. Закрытия являются общим механизмом реализации для такой "функциональной фабрики". Я часто принимаю решение использовать закрытия в Стратегическая модель , когда стратегия изменяется данными во времени выполнения.

На языке, который позволяет анонимное определение блока - например, Ruby, C# - закрытия могут использоваться для реализации (что сумма к) новых новых управляющих структур. Отсутствие анонимных блоков среди ограничения закрытий в Python .

14
ответ дан ESV 24 November 2019 в 10:32
поделиться

Честно говоря, я понимаю закрытия отлично кроме, я никогда не соглашался с тем, что точно является вещью, которая является "закрытием" и что является так "закрытием" об этом. Я рекомендую бросить искать любую логику позади выбора термина.

Так или иначе, вот мое объяснение:

def foo():
   x = 3
   def bar():
      print x
   x = 5
   return bar

bar = foo()
bar()   # print 5

идея ключа А здесь состоит в том, что функциональный объект, возвращенный из нечто, сохраняет рычаг к локальному var 'x' даже при том, что 'x' вышел из объема и должен быть более не существующим. Этот рычаг к самому var, не только значение, которое var имел в то время, поэтому когда панель называют, это печатает 5, не 3.

Также быть ясным, что Python 2.x ограничил закрытие: нет никакого способа, которым я могу изменить 'x' в 'панели', потому что запись 'x = bla' объявила бы локальный 'x' в панели, не присвоилась бы к 'x' нечто. Это - побочный эффект assignment=declaration Python. Для обхождения этого Python 3.0 представляет нелокальное ключевое слово:

def foo():
   x = 3
   def bar():
      print x
   def ack():
      nonlocal x
      x = 7
   x = 5
   return (bar, ack)

bar, ack = foo()
ack()   # modify x of the call to foo
bar()   # print 7
14
ответ дан Jegschemesch 24 November 2019 в 10:32
поделиться

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

Это назвало закрытие, потому что это "закрывается по" внешней переменной (константе) - т.е. это не просто функция, но и корпус среды, где функция была создана.

В следующем примере, называя закрытие g после изменения x также изменит значение x в g, с тех пор g завершения по x:

x = 0

def f():
    def g(): 
        return x * 2
    return g


closure = f()
print(closure()) # 0
x = 2
print(closure()) # 4
6
ответ дан Frozen Flame 24 November 2019 в 10:32
поделиться

Вот типичный вариант использования для закрытий - обратные вызовы для элементов GUI (это было бы альтернативой разделению на подклассы класса кнопки). Например, можно создать функцию, которая будет вызвана в ответ на нажатие кнопки, и "близко" по следующим переменным в родительском объеме, которые необходимы для обработки щелчка. Таким образом, можно обеспечить электричеством довольно сложные интерфейсы от той же функции инициализации, встроив все зависимости в закрытие.

3
ответ дан 24 November 2019 в 10:32
поделиться

Лучшее объяснение я когда-либо пила закрытия должно было объяснить механизм. Это прошло примерно так:

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

Теперь ослабляют ограничение, что каждый узел может иметь только одного ребенка.

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

-2
ответ дан ConcernedOfTunbridgeWells 24 November 2019 в 10:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: