파이썬 클로져(Closure)
클로저(Closure) 함수
내부함수
파이썬은 아래와 같이 내부함수를 정의해서 사용할수있다.
def outer_fucntion(a, b):
def inner_function(c, d):
return c + d
return inner(a, b)
print(outer_function(3, 5))
>>> 출력결과
> 8
클로져 개념
내부함수는 클로져 처럼 행동할수있다.
클로저는 일반 함수와 다르게, 자신의 영역 밖에서 호출된 함수의 변수값과 레퍼런스를 복사, 저장, 접근을 가능하게 한다.
컴퓨터 언어에서 클로저(Closure)는 일급 객체 함수(first-class functions)의 개념을 이용하여 스코프(scope)에 묶인 변수를 바인딩 하기 위한 일종의 기술이다. 기능상으로, 클로저는 함수를 저장한 레코드(record)이며, 스코프(scope)의 인수(Factor)들은 클로저가 만들어질 때 정의(define)되며, 스코프 내의 영역이 소멸(remove)되었어도 그에 대한 접근(access)은 독립된 복사본인 클로저를 통해 이루어질 수 있다.
def say_words(msg):
def say_sentence():
return "안녕? 이걸 출력해줘! : {}".format(msg)
return say_sentence
a = say_words("출출하다")
print("a는 무엇일까? : ", a)
print("a의 타입은 무엇일까? : ", type(a))
print("a가 함수라는 걸 알았다. 괄호를 붙여보자. ====> ", a())
>>> 출력결과
> a는 무엇일까? : <function say_words.<locals>.say_sentence at 0x7fc2c039c0d0>
> a의 타입은 무엇일까? : <class 'function'>
> a가 함수라는 걸 알았다. 괄호를 붙여보자. ====> 안녕? 이걸 출력해줘! : 출출하다
위에서 say_sentece()에 msg를 전달해준 적이 없는데도 메세지를 출력해준다.
a라는 변수에 say_words()라는 함수를 할당 해줬는데,
a함수를 호출하니까 <function say_words.
원래는 function 만 출력되어야하는데 locals 가 붙는다.
그 이유는 다음과같다.
클로저는 다른 함수에 의해 동적으로 생성되고, 바깥 함수로부터 생성된 변수값을 알고 있는 변수이다.
클로저의 변수 추적하기
클로져는 바깥함수로 부터 생성된 변수를 사용하기때문에 어디선가 저장하고 있을것이다.
def say_words(msg):
def say_sentence():
return "안녕? 이걸 출력해줘! : {}".format(msg)
return say_sentence
a = say_words("출출하다")
print("a는 무엇일까? : ", a)
추적 1
print(dir(a)) dir(a) : 객체(a)가 자체적으로 가지고 있는 변수나 함수를 보여준다. 가장 큰 단위의 조사라고 보면 된다.
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
추적 2
print(type(a.clousre)
<class 'tuple'>
추적 3
print(a.closure) cell : cell이 뭔가 찾아보니 여러 범위(scope)에서 참조할 수 있는 값을 저장할 수 있는 객체라고 한다.
(<cell at 0x7fc2c0c2fdf8: str object at 0x7fc2c03abd40>,)
추적 4
print(dir(a__closure[0]__))
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
마지막에 cell_contents 를 숨기고 있었다.
추적 5
print(a.closure[0].cell_contents)
출출하다
라는 것이 출력된다.
출처 : https://whatisthenext.tistory.com/112