함수 서명에서 변수를 제거하기 위해 클로저 내에 변수를 캡슐화하는 것은 효율적인 코드 구조화에 자주 사용되는 기술입니다. 그러나 중첩되지 않은 람다의 경우 클로저는 변수의 최종 값을 유지하므로 반복 변수를 기반으로 특정 값에 액세스하려고 시도할 때 문제가 발생합니다.
제공된 코드 조각을 고려하세요.
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의 경우 Lambda x: test_fun(n, x)를 실행하면 변수 n이 람다 정의 중에는 평가되지 않습니다. 대신 평가는 람다 호출 시에만 발생합니다. 이 시점에서 n은 루프의 마지막 값(이 경우 'c')을 보유합니다. 결과적으로 함수 f는 입력 x에 관계없이 항상 'c'를 n의 값으로 활용합니다.
이 문제를 해결하고 원하는 기능을 달성하려면 변수 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 함수에 캡처되어 람다 내에서 적절한 범위 지정을 보장합니다.
이해 및 효과적인 코드 디자인과 디버깅을 위해서는 클로저에서 변수 범위 지정을 관리하는 것이 필수적입니다. 주요 내용은 다음과 같습니다.
위 내용은 중첩되지 않은 Lambda 클로저에서 변수 범위 문제를 처리하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!