Инкапсуляция переменных внутри замыканий для удаления их из сигнатур функций — это метод, часто используемый для эффективного структурирования кода. Однако в случае невложенных лямбда-выражений замыкание сохраняет окончательное значение переменной, что приводит к проблемам при попытке доступа к определенным значениям на основе итерируемой переменной.
Рассмотрите предоставленный фрагмент кода:
names = ['a', 'b', 'c'] def test_fun(name, x): print(name, x) def gen_clousure(name): return lambda x: test_fun(name, x) funcs1 = [gen_clousure(n) for n in names] funcs2 = [lambda x: test_fun(n, x) for n in names] # Expected output for funcs1 for f in funcs1: f(1) # Unexpected output for funcs2 (returns last element for all cases) for f in funcs2: f(1)
Понимание причины этого несоответствия имеет решающее значение для эффективного использования замыканий.
Основной концепцией в этой ситуации является определение области видимости переменных в замыканиях. . Замыкания по своей сути содержат имена переменных, а не их значения. Это означает, что оценка переменной происходит при запуске выполнения лямбды, а не во время определения лямбды.
В случае funcs2, когда вы выполняете лямбду x: test_fun(n, x), переменная n не оценивается во время определения лямбды. Вместо этого оценка происходит только при вызове лямбды. В этот момент n содержит последнее значение из цикла (в данном случае это «c»). Следовательно, функция f всегда использует «c» в качестве значения n, независимо от входных данных x.
Чтобы решить эту проблему и достичь желаемой функциональности, переменная n должна быть зафиксирована в области видимости лямбда-функции. Этого можно достичь, передав переменную в качестве аргумента в лямбду, как показано в следующем примере:
funcs2 = [lambda x: test_fun(n, x) for n in names if 2 > 0]
Включая этот дополнительный оператор if, который всегда выполняется, мы заставляем лямбду принимать значение n в качестве аргумента, обеспечивая ожидаемое персонализированное поведение во всех случаях.
В качестве альтернативы вы можете обернуть невложенную лямбду во вложенную функцию, эффективно предотвращая доступ к необъявленным переменным в области видимости. Следующий код иллюстрирует этот подход:
def makeFunc(n): return lambda x: x n stuff = [makeFunc(n) for n in [1, 2, 3]] for f in stuff: print(f(1))
Здесь переменная n фиксируется в функции makeFunc, обеспечивая правильную область видимости в лямбда-выражении.
Понимание области видимости переменных и управление ею в замыканиях необходим для эффективного проектирования и отладки кода. Ключевые выводы:
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3