어떤 함수의 내부 함수가 외부 함수의 변수를 참조할 때, 외부 함수가 종료된 후에도 내부 함수가 외부 함수의 변수를 참조할 수 있도록 어딘가에 저장하는 함수
클로저 함수 조건
- 어떤 함수의 내부 함수일 것
- 그 내부 함수가 외부 함수의 변수를 참조할 것
- 외부 함수가 내부 함수를 리턴할 것
def func(msg):
message = 'Hello '+ msg
def say():
print(message)
return say
f = func('python')
f()
#출력 결과
#Hello python
중첩 함수인 say가 외부 함수인 func의 변수 message를 참조하기 때문에
message 변수와 say의 환경을 저장하는 클로저가 동적으로 생성
되었고
f가 실행될 때 해당 클로저를 참조해서 message 값 출력 가능!
__closure__
확인❗ dir()
: 어떤 객체를 인자로 넣어주면 해당 객체가 어떤 변수와 메소드를 가지고 있는지 나열
def func(msg):
message = 'Hello '+ msg
def say():
print(message)
return say
f = func('python')
print(dir(f))
#출력 결과
#['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
3번째 인덱스에 __closure__
존재
__closure__
값 확인def func(msg):
message = 'Hello '+ msg
def say():
print(message)
return say
f = func('python')
print(type(f.__closure__))
print(f.__closure__)
print(dir(f.__closure__[0]))
#출력 결과
#<class 'tuple'>
#(<cell at 0x0198F7D8: str object at 0x01AC8020>,)
#['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__ '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
dir(f.__closure__[0])
마지막에 cell_contents
존재__closure__
의 cell_contents 확인❗ 클로저가 저장되는 경로 __closure__[0].cell_contents
def func(msg):
message = 'Hello '+ msg
def say():
print(message)
return say
f = func('python')
print(f.__closure__[0].cell_contents)
#출력 결과
#Hello python
지역 변수와 코드를 묶어서 사용하고 싶을 때
클로저에 속한 지역 변수는 바깥에서 직접 접근할 수 없음
=> 데이터를 숨기고 싶을 때
보통 클로저는 람다 표현식과 함께 사용하는 경우 많음
def calc():
a = 3
b = 5
return lambda x: a*x + b
c = calc()
print(c(10))
#출력 결과
#35
참고
https://tibetsandfox.tistory.com/9
https://wikidocs.net/10307
https://dojang.io/mod/page/view.php?id=2366