파이썬 클로저 문법 질문..

조회수 654회

클로저는 외부함수를 의미하는 것인지, 아니면 내부함수를 부르는 명칭인지 헷갈리네요..

그리고 문법적으로는 내부함수가 외부함수 종료후에도 외부함수의 변수를 기억한다고 설명되어 있습니다.

그럼 클로저의 경우는 함수가 종료된 후에는 함수 내의 변수가 메모리에서 사라진다는 원칙의 예외가 되는 것인가요? 즉, 외부함수가 종료되어도 내부함수에서 사용하는 외부함수의 변수는 메모리에서 사라지지 않고 계속 살아있다는 것인지 궁금합니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 기본적으로 내부함수가 있으면 클로져라고 지칭할 수 있습니다.

    외부함수쪽의 변수들을 캡쳐를 하게 되는데 아마 이것을 질문하는 듯 합니다.

    또한 파이썬은 gc가 있는 환경으로 함수가 종료되어도 바로 메모리가 정리될 수 없습니다. 그것은 오로지 gc 메카니즘의 몫이고 이것은 파이썬 버전마다 다를수도 있습니다.

    파이썬의 클로져가 변수를 다루는 것을 이해하려면 __closure__ 를 이해해야 합니다.

    def outer():
        v1, v2, v3 = 1, 2, 3
        def inner():
            s = v1 + v2 + v3   # v1, v2, v3 변수를 사용함으로 내부함수에서 캡쳐된다.
            pass
        return inner
    innerF = outer()
    innerF()
    
    innerF.__closure__    # __closure__ 필드는 캡쳐된 변수를 저장하는 튜플이다
    (<cell at 0x7ff5d6ba5228: int object at 0x7ff6202494e0>,
     <cell at 0x7ff5d6ba5978: int object at 0x7ff620249500>,
     <cell at 0x7ff5d6ba5e28: int object at 0x7ff620249520>)
    
    for v in innerF.__closure__:    # __closure__ 필드에 저장된 값을 출력
        print(v.cell_contents)
    1
    2
    3
    
    

    한발 더 나아가서...외부 함수의 변수를 사용하지 않을때를 봅시다.

    def outer():
        v1, v2, v3 = 1, 2, 3
        def inner():
            #s = v1 + v2 + v3    #주석처리
            pass
        return inner
    innerF = outer()
    innerF()
    
    innerF.__closure__    # 결과 없음
    
    for v in innerF.__closure__:
        print(v.cell_contents)
    
    TypeError: 'NoneType' object is not iterable
    
    

    클로져 즉 내부함수에서 외부함수의 변수를 사용하지 않는다면 컴파일시점에 그것을 알 수 있고(유지할지 여부) __closure__에 저장하지 않습니다.

    즉 외부함수의 변수를 참조한다기 보다 내부함수에 복사(__closure__)되어 저장하고 있다고 이해하면 됩니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)