함수 서명에서 변수를 제거하기 위해 클로저 내에 변수를 캡슐화하는 것은 효율적인 코드 구조화에 자주 사용되는 기술입니다. 그러나 중첩되지 않은 람다의 경우 클로저는 변수의 최종 값을 유지하므로 반복 변수를 기반으로 특정 값에 액세스하려고 시도할 때 문제가 발생합니다.
제공된 코드 조각을 고려하세요.
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는 입력 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 함수에 캡처되어 람다 내에서 적절한 범위 지정을 보장합니다.
변수 범위 지정 이해 및 관리 효과적인 코드 디자인과 디버깅을 위해서는 클로저가 필수적입니다. 주요 내용은 다음과 같습니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3