에서 c()를 여러번 사용하게되면 출력하는 i의 값이 왜 늘어나는지 모르겠습니다.
호출될때마다 i=0으로 계속 초기화가 되는게 아닌가요..?
이전 답변을 참고하세요.
https://dojang.io/mod/forum/discuss.php?d=1592&parent=3621
다음 예제를 실습해보세요.
def counter():
i = 0
def count():
nonlocal i
i += 1
return i
return count
c = counter()
for i in range(10):
print(c(), end=' ')
print()
c2 = counter()
for i in range(20):
print(c2(), end=' ')
print()
print(c())
print(c2())
실행 결과는
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 11 21
클로저는 호출될 때 함수가 하나 생성되는 것입니다.
c = counter()를 호출했을 때 counter()를 한 번 호출한 것이고, counter에 정의된 것에 따라 함수를 호출해서 c에 할당한 것입니다.
새로 생성된 함수는 c에 있으니까 c()를 통해 호출하는 것입니다.
클로저 함수는 한 번 생성된 이후 초기화된 적이 없으므로 i의 값이 계속 유지됩니다.
c2 = counter()는 counter()를 호출한 것이니까 새로운 클로저 함수를 생성합니다. 이때 i = 0인 값이 만들어지고, 이는 counter()를 처음 호출했을 때 만들어진 것과는 다른 함수입니다. c2에 할당된 변수 i는 c2에 속하는 변수입니다. 따라서 c2()를 호출할 때마다 i의 값이 증가하지만 이는 c 함수와는 상관없습니다.
c함수의 변수 i와 c2함수의 변수 i는 별개입니다.
c=counter() 로 c에 counter함수를 호출해서 할당했고
할당된 함수를 c()를 통해서 호출하게 되면 아래의 counter함수에 따라서 i=0을 실행하고 count 함수에의해 i에다 1을 더한 1이 값으로 나오고 다시 i=0이 되고 i에다 1을더한 1이 값으로나오고 이런식으로 실행되는것이 아닌가요?
def counter():i = 0 은 실행이 되어야 하는게 아닌건가요...? i=0이 한번만 실행되는이유가 뭔가요?
i = 0
def count():
nonlocal i
i += 1
return i
return count
클로저이니까 counter()를 호출했을 때 함수를 생성하는 것이고
생성되는 함수에서 i는 전역 변수에 해당합니다.
따라서 i = 0은 한 번만 실행되는 것이고,
c()로 호출되는 건 count() 함수 본문이겠죠.
c()를 호출할 때마다 i를 리셋하고 싶으면
def counter():이렇게 하면 됩니다.
def count():
i = 0
i += 1
return i
return count
호출할 때마다 1만 반환될 겁니다.
상단 고정에 있는 파이썬 시각화를 이용하세요.
이와 같이 i가 글로벌에 속해 있고, nonlocal i로 로컬이 아니라 글로벌에 있는 i를 변수로 사용하라고 count 안에서는 선언한 겁니다.
파이썬 시각화로 코드를 이것저것 고쳐가면서 동작을 이해하세요.
Global 프레임은 파이썬의 전역 변수들이 속하는 영역입니다.
함수 정의 없이 사용하는 변수 등은 모두 글로벌 프레임입니다.
def counter(start):
def count():
nonlocal start
start += 1
return start
return count
c = counter(1)
for i in range(10):
print(c(), end=' ')
print()
c2 = counter(10)
for i in range(20):
print(c2(), end=' ')
print()
print(c())
print(c2())
여기서도 nonlocal start가 없으면 counter 함수에 인자로 전해지는 변수 start는 count 바깥에서만 접근할 수 있고, count 내부에서는 접근할 수 없습니다. nonlocal start 선언을 지워보면 바로 에러가 나고, 그런 변수가 없다고 메시지가 표시될 겁니다. count가 보기에 start는 글로벌 프레임에 속한 것이니까요. count 함수는 count 함수 안에서 선언된 변수들만 로컬 프레임으로 볼 수 있습니다. 서로 다른 함수가 다른 함수의 변수에 마음대로 접근할 수 없으니까 각각의 변수는 함수 안에서만 유효합니다. 그러나 함수 바깥에 접근할 필요가 있을 때는, 전역 변수에 접근할 때는 nonlocal 선언으로 이 변수는 전역에 있습니다. 전역 변수로 사용하세요 라고 하는 것입니다. 클로저를 만들 때도 인자 자체가 count가 보기엔 바깥에 있으니까 접근하려면 nonlocal이 필요합니다.
다양하게 코드를 고쳐보고 실험하고, 책을 다시 반복해서 읽으세요.