Вот самый маленький фрагмент кода для проверки готовности DOM, который работает во всех браузерах (даже IE 8):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
Объекты являются данными с присоединенными методами, закрытия являются функциями с присоединенными данными.
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
Это просто: функция, которой ссылочные переменные от содержания определяют объем, потенциально после потока управления, оставила тот объем. Тот последний бит очень полезен:
>>> 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 надлежащие закрытия.
Мне нравится это грубое, сжатое определение :
функция А, которая может относиться к средам, которые больше не активны.
я добавил бы
, закрытие А позволяет Вам связывать переменные в функцию , не передавая их как параметры .
Декораторы, которые принимают параметры, являются общим использованием для закрытий. Закрытия являются общим механизмом реализации для такой "функциональной фабрики". Я часто принимаю решение использовать закрытия в Стратегическая модель , когда стратегия изменяется данными во времени выполнения.
На языке, который позволяет анонимное определение блока - например, Ruby, C# - закрытия могут использоваться для реализации (что сумма к) новых новых управляющих структур. Отсутствие анонимных блоков среди ограничения закрытий в Python .
Честно говоря, я понимаю закрытия отлично кроме, я никогда не соглашался с тем, что точно является вещью, которая является "закрытием" и что является так "закрытием" об этом. Я рекомендую бросить искать любую логику позади выбора термина.
Так или иначе, вот мое объяснение:
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
Я никогда не слышал о транзакциях, используемых в том же контексте в качестве объяснения, что закрытие и здесь действительно нет никакой семантики транзакции.
Это назвало закрытие, потому что это "закрывается по" внешней переменной (константе) - т.е. это не просто функция, но и корпус среды, где функция была создана.
В следующем примере, называя закрытие 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
Вот типичный вариант использования для закрытий - обратные вызовы для элементов GUI (это было бы альтернативой разделению на подклассы класса кнопки). Например, можно создать функцию, которая будет вызвана в ответ на нажатие кнопки, и "близко" по следующим переменным в родительском объеме, которые необходимы для обработки щелчка. Таким образом, можно обеспечить электричеством довольно сложные интерфейсы от той же функции инициализации, встроив все зависимости в закрытие.
Лучшее объяснение я когда-либо пила закрытия должно было объяснить механизм. Это прошло примерно так:
Воображают Вашу стопку программы как вырожденное дерево, где каждый узел имеет только одного ребенка, и единственная вершина является контекстом Вашей в настоящее время выполняющейся процедуры.
Теперь ослабляют ограничение, что каждый узел может иметь только одного ребенка.
, Если Вы делаете это, у Вас может быть конструкция ('урожай'), который может возвратиться из процедуры, не отбрасывая локальный контекст (т.е. это не выталкивает его от стека, когда Вы возвращаетесь). В следующий раз, когда процедура вызывается, вызов берет старый стек кадр (дерева) и продолжает выполняться, где это кончило.