최근에 나는 파이썬으로 놀기 시작했고 클로저가 작동하는 방식에 독특한 것을 발견했습니다. 다음 코드를 고려하십시오.
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등