1 minute read

클로저(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..say_sentence at 0x7fc2c039c0d0> 가된다.

원래는 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

Categories:

Updated: