클로저
클로저란?
클로저는 함수가 종료되어도 자원을 사용할 수 있는 함수이다. 여기서 자원은 변수를 의미한다.
클로저는 아래 3가지 조건을 만족해야 한다.
- 내부 함수여야 한다. (내부함수는 함수 안에서 정의되는 함수이다.)
- 외부 함수의 변수를 참조해야 한다.
- 외부 함수가 내부 함수를 반환해야 한다
클로저 함수 구현
def outer(name):
def inner():
print(name, "님 안녕하세요!")
return inner
func = outer("SYJ") # outer 함수 종료되는 시점
>>> func()
SYJ 님 안녕하세요!
outer 함수는 종료되었지만 inner함수는 outer 함수가 가지고 있는 변수(자원)을 가지고 코드를 실행했다.
이는 __closer__
라는 공간 안에 name이라는 데이터가 저장되어 있기 때문에 가능하다.
조건과 같이 다시 살펴보면 inner 함수는 내부함수이고, name이라는 외부 함수의 변수를 참고하고 있고, 외부 함수가 내부함수를 return 하고 있다. 따라서 inner 함수는 클로저라고 할 수 있다.
데이터의 저장 위치
def greeting(name, age, gender):
def inner():
print(name, "님 안녕하세요!")
print("나이: ", age)
print("성별: ", gender)
return inner
closure = greeting('A', 27, 'female')
closure()
A 님 안녕하세요!
나이: 27
성별: female
>>> print(type(closure.__closure__))
<class 'tuple'>
>>> print(closure.__closure__)
(<cell at 0x7fe1a3073b80: int object at 0x959160>, <cell at 0x7fe1a3073c40: str object at 0x7fe1a3083430>, <cell at 0x7fe1a3073dc0: str object at 0x7fe1a5962c30>)
>>> print(dir(closure.__closure__[0]))
['__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']
>>> print(closure.__closure__[0].cell_contents)
27
>>> for i in closure.__closure__:
... print(i.cell_contents)
...
27
female
A
확인해보면 closure.__closure__[0]
의 cell_contents 속성안에 외부함수의 데이터를 가지고 있다.
이러한 데이터는 사실 전역변수를 사용해서 대체가 가능하지만 전역변수는 사용을 최소화하는 것이 좋기 때문에 클로저를 사용한다.