본문 바로가기
코딩 연습/코딩배우기

파이썬의 일급 객체 함수 개념을 이용한 클로저(closure) 연습

by good4me 2020. 11. 10.

goodthings4me.tistory.com

 

파이썬 클로저(closure)

■ 클로저는 스코프에 묶인 변수를 바인딩 하기 위한 기술로, 파이썬에서 __closure__는 cell(셀)로 이루어진 튜플이며, cell 객체는 __closure__의 free variables(변수)를 저장하기 위해 사용되고, 각 cell에는 저장된 값을 확인할 수 있는 cell_contents라는 변수(속성)가 있다.

def closure_ex1():
    x = 1
    
    def inner():
        y = 2
        return x + y
    
    return inner
    

r1 = closure_ex1()
print(r1, type(r1))  ## 리턴값은 inner 함수의 참조값
# <function closure_ex1.<locals>.inner at 0x0000023B36A21BF8> <class 'function'>

print(hasattr(r1, '__closure__'))  ## r1에 속성 __closure__ 있는지
# True

print(r1.__closure__)  ## int x의 위치는
# (<cell at 0x0000023B369D5FD8: int object at 0x00007FF9E5F79340>,)

print(type(r1.__closure__[0]))
# <class 'cell'>

for attr in dir(r1.__closure__[0]):  ## 튜플의 res.__closure__[0] 속성들은
    print(attr)

#__class__
#__delattr__
#__dir__
#__doc__
#__eq__
#__format__
#__ge__
#__getattribute__
#__gt__
#__hash__
#__init__
#__init_subclass__
#__le__
#__lt__
#__ne__
#__new__
#__reduce__
#__reduce_ex__
#__repr__
#__setattr__
#__sizeof__
#__str__
#__subclasshook__
#cell_contents


## 객체의 변수(속성)인 cell_contents
print(r1.__closure__[0].cell_contents)  ## int x의 값은
# 1

print(r1())  ## 리턴된 함수의 실행
# 3
def closure_ex2(x, y):
    x = x
    y = y
    
    def inner():
        return x ** y
    
    return inner

r2 = closure_ex2(2, 32)
print(r2)
# <function closure_ex2.<locals>.inner at 0x0000023B36A9C8C8>

print(r2.__closure__)
# (<cell at 0x0000023B36ACDD68: int object at 0x00007FF9E5F79360>, <cell at 0x0000023B36ACDD98: int object at 0x00007FF9E5F79720>)

for c in r2.__closure__:
    print(c.cell_contents)

#2
#32
   
print(r2())
# 4294967296

good4me.co.kr

 

def closure_ex3(x, y):
    x = x
    y = y
    
    def inner(x, y):
        return x ** y
    
    return inner


r3 = closure_ex3(2, 32)
print(r3)
# <function closure_ex2.<locals>.inner at 0x0000023B36ABFAE8>

print(r3.__closure__)
# None

#print(r3())
# TypeError: inner() missing 2 required positional arguments: 'x' and 'y'

## closure_ex3 함수의 x, y 변수와 내부 inner 함수의 x, y 변수는 다름
print(r3(2, 32))
# 4294967296




## closure_ex3 내 inner 함수를 람다 함수로 변경
def closure_ex4(x, y):
    x = x
    y = y
    
    return lambda x, y: x ** y

    
r4 = closure_ex4(2, 32)
print(r4)
# <function closure_ex4.<locals>.<lambda> at 0x0000023B36AD1048>

print(r4.__closure__)  
# None

print(r4(2, 32))
# 4294967296

 

댓글