Передача аргументов при повторении python 3 [duplicate]

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

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}

89
задан Martijn Pieters 27 March 2017 в 09:12
поделиться

3 ответа

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

Тело функции скомпилировано, а «свободные» переменные (не определенные в самой функции путем назначения) проверяются, а затем привязываются как замыкающие ячейки к функции, причем код использует индекс для ссылки на каждую ячейку. pet_function, таким образом, имеет одну свободную переменную (cage), которая затем ссылается через ячейку замыкания, индекс 0. Сама замыкание указывает на локальную переменную cage в функции get_petters.

Когда вы на самом деле вызываете функцию, это закрытие затем используется для просмотра значения cage в окружающем пространстве во время вызова функции . Здесь кроется проблема. К тому моменту, когда вы вызываете свои функции, функция get_petters уже выполняется, вычисляя ее результаты. Локальная переменная cage в какой-то момент во время этого выполнения была назначена каждой из строк 'cow', 'dog' и 'cat', но в конце функции cage содержит это последнее значение 'cat'. Таким образом, когда вы вызываете каждую из динамически возвращаемых функций, вы получаете значение 'cat'.

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

  • Пример частичной функции, используя functools.partial() :
    from functools import partial
    
    def pet_function(cage=None):
        print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, partial(pet_function, cage=cage)))
    
  • Создание нового примера области видимости:
    def scoped_cage(cage=None):
        def pet_function():
            print "Mary pets the " + cage.animal + "."
        return pet_function
    
    yield (animal, partial(gotimes, scoped_cage(cage)))
    
  • Связывание переменной в качестве значения по умолчанию для параметра ключевого слова:
    def pet_function(cage=cage):
        print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, pet_function))
    

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

96
ответ дан Martijn Pieters 19 August 2018 в 16:18
поделиться
  • 1
    Я ударил головой о эту стену в течение 3 часов сегодня по сценарию для работы. Ваш последний момент очень важен и является основной причиной, почему я столкнулся с этой проблемой. У меня есть обратные вызовы с закрытием в изобилии по всему моему коду, но попытка использовать ту же технику в цикле - это то, что меня достало. – DrEsperanto 7 March 2018 в 05:11

Это проистекает из следующего

for i in range(2): 
    pass

print i is 1

после того, как итерирование значения i лениво сохранено в качестве его окончательного значения.

В качестве генератора функция будет работать (т. е. печатать каждое значение по очереди), но при преобразовании в список он запускается через генератор, поэтому все вызовы cage (cage.animal) возвращают кошек.

5
ответ дан coldspeed 19 August 2018 в 16:18
поделиться

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

Итак, когда вы делаете

funs = list(get_petters())

Вы генерируете 3 функции, которые найдут последнюю созданную клетку.

Если вы замените свой последний цикл на:

for name, f in get_petters():
    print name + ":", 
    f()

Фактически вы получите:

cow: Mary pets the cow.
dog: Mary pets the dog.
cat: Mary pets the cat.
11
ответ дан Nicolas Barbey 19 August 2018 в 16:18
поделиться
Другие вопросы по тегам:

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