Programming,  Python

[Python] Closure

Python에서 함수 안에서 선언된 함수의 return을 return하는 함수를 closure라고 부른다.

def calc():
    a = 3
    b = 5
    def mul_add(x):
        return a * x + b    
    return mul_add          
 
c = calc()
print(c(1), c(2), c(3), c(4), c(5))
8 11 14 17 20

위 코드에서 calc() 함수 안에 local variable인 a와 b가 mul_add() 함수에 저장이 된다. 함수가 데이터로 취급될 때는 함수가 정의된 곳의 주변 환경정보가 함께 저장된다.
데이터 구조를 그림으로 그린다면 아래와 같이 구성될 것이다.

실제 closure의 주소와 내부 컨텐츠를 찍어보면 아래와 같이 나온다.

c.__closure__
c.__closure__[0].cell_contents
(<cell at 0x00000257443E0A08: int object at 0x00007FFE8FF9A1D0>,
<cell at 0x00000257443E0B58: int object at 0x00007FFE8FF9A210>)
3

참고로 lambda function을 쓰더라도 일반 함수와 동일하게 된다.

Closure 내부에서 정의한 변수에 접근

Closure로 함수 내부에서 정의한 변수에 접근 방법 또한 이전에 소개한것과 동일하게 nonlocal 키워드를 통해 가능하다.

def sample():
    n = 0           
    def func():
        print('n =', n)
    
    def get_n():
        return n

    def set_n(value):
        nonlocal n
        n = value

    func.get_n = get_n
    func.set_n = set_n
    return func

if __name__ == '__main__':
    f = sample()
    f()
    n= 0
    f.set_n(10)
    f()
    print(f.get_n())
n = 0
n = 10
10

Closure를 통해 내부 변수를 변경하기 위해선 get_n()set_n()과 같은 property를 만들어서 내부 함수와 연결시켜서 내부 변수를 설정 가능하다. 여기서 물론 nonlocal 키워드를 반드시 사용해야지 자신의 밖에 scope에 접근 가능하다.

실제 함수의 property를 보려면 __dict__ 에 존재한다.

print(f.__dict__)
{‘get_n’: .get_n at 0x00000257443D8948>, ‘set_n’: .set_n at 0x00000257443D8AF8>}

Leave a Reply

Your email address will not be published. Required fields are marked *