최근에 나는 파이썬으로 놀기 시작했고 클로저가 작동하는 방식에 독특한 것을 발견했습니다. 다음 코드를 고려하십시오.
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
단일 입력을 사용하여 숫자로 추가 된 해당 입력을 반환하는 간단한 함수 배열을 작성합니다. 함수는 for
반복자가에서 i
실행되는 루프로 구성 0
됩니다 3
. 이러한 각 숫자에 대해 lambda
함수를 작성 i
하여 함수의 입력에 추가 하는 함수가 작성 됩니다. 마지막 줄 은 매개 변수로 두 번째 lambda
함수를 호출합니다 3
. 놀랍게도 출력은이었습니다 6
.
나는을 기대했다 4
. 내 추론은 : 파이썬에서는 모든 것이 객체이므로 모든 변수는 그것에 대한 포인터입니다. 에 대한 lambda
클로저를 만들 때 i
현재 가리키는 정수 객체에 대한 포인터를 저장할 것으로 예상했습니다 i
. 이는 i
새로운 정수 객체 가 할당 될 때 이전에 생성 된 클로저에 영향을 미치지 않아야 함을 의미합니다 . 안타깝게도 adders
디버거 내 에서 배열을 검사하면 배열이 작동하는 것으로 나타납니다. 모든 lambda
함수는 i
, 의 마지막 값을 참조하여 3
결과를 adders[1](3)
반환 6
합니다.
다음에 대해 궁금해합니다.
- 클로저는 정확히 무엇을 포착합니까?
lambda
값을 변경할i
때 영향을받지 않는 방식으로 현재 값을 캡처 하도록 함수 를 설득하는 가장 우아한 방법은 무엇입니까i
?
i
네임 스페이스 는 어떻게 남겨 집니까 ?
print i
, 루프 후에는 작동하지 않을 것이라고 말했습니다 . 그러나 나는 그것을 직접 테스트했으며 이제는 당신이 무엇을 의미하는지 알았습니다. 파이썬에서 루프 변수 뒤에 루프 변수가 남아 있다는 것을 몰랐습니다.
if
, with
, try
등