[Python] First-class 함수, Closure 함수, 데코레이터 (Decorator)
decorator를 알기 전 First-class 함수와 Closure 함수를 알아야 한다.
우선 제일 중요한 것은
파이썬에는 함수는 객체다
라는 것이다.
First-class function
코드부터 보자
def info(name):
return 'Hi ' + name
info함수는 아래와 같이 실행할 수 있다.
info('Sso')
또한 함수는 객체이기 때문에 변수에 할당할 수 있다.
func = info
print(func('Sso'))
Hi Sso
다른 코드를 봐보자
def one(num):
return num + 1
def two(num):
return num + 2
def three(num):
return num + 3
위에 정의한 함수를 다른 함수의 인자로 넣을 수 있다.
def sum_num(func, num):
print(func(num))
sum_num(one, 3)
sum_num(two, 3)
sum_num(three, 3)
4
5
6
sum_num함수를 저렇게 극단적으로 쓰진 않겠지만.. 어쨌든 이 또한 가능하다.
마지막으로 함수를 return할 수 있다.
def letter(text):
msg = text
def write_msg():
print(msg)
return write_msg
send = letter('HBD!')
send()
HBD!
letter함수 안에 write_msg 중첩함수를 정의했다.
위에서 함수를 변수에 할당할 수 있었기에 send 변수에 letter 함수를 할당하였고
return값이 write_msg 함수이기 때문에
send()로 write_msg 함수를 실행시킬 수 있다.
원래 중첩함수는 외부에서 접근할 수 없다. (write_msg()는 오류남)
하지만 함수의 반환값으로 중접함수를 사용하면 접근이 가능하다
본래 letter 함수를 삭제해보겠다
del letter
send()
HBD!
letter 함수를 삭제했는데도 HBD!가 출력됐다.
이는 letter함수를 실행할 때 넘어온 text의 값이 유지된다는 것이다.
지역 변수 값이 살아있다!
현재 사용하려는 함수의 외부에서 선언한 변수를 자유변수라고 한다.
직접 코드로 확인해보자.
print(send.__code__.co_freevars)
('msg',)
mgs가 저장되어져 있음을 확인할 수 있다.
실제 값을 확인해보자.
print(send.__closure__[0].cell_contents)
HBD!
앞서 msg(자유변수)에 HBD!를 넣어줬기 때문에 해당 값이 저장돼있음을 확인할 수 있다.
※ 주의 ※
def letter(text):
msg = text
def write_msg():
msg += '!!!!!'
print(msg)
return write_msg
send = letter('HBD!')
send()

위에서 자유변수를가 함수가 끝난 이후에도 살아있음을 확인했다.
하지만 write_msg함수 내에서 자유변수 msg를 변경하려고 하자 위와 같은 에러가 발생했다.
write_msg함수 내 msg가 할당되기 전에 사용했다는 에러이다.
write_msg함수 바깥쪽에 msg와 안쪽에 msg가 같다는 예약어가 필요하다.
바로 nonlocal 예약어이다.
def letter(text):
msg = text
def write_msg():
nonlocal msg
msg += '!!!!!'
print(msg)
return write_msg
send = letter('HBD!')
send()

제대로 실행된다.
Closure function
이게 바로 Closure function이다. (하나의 기법을 의미)
위에서 클로저 함수는 write_msg가 된다.
위키에 따르면 클로저 함수를 다음과 같이 정의한다.
클로저는 함수를 저장한 레코드(record)이며, 스코프(scope)의 인수(Factor)들은 클로저가 만들어질 때 정의(define)되며, 스코프 내의 영역이 소멸(remove)되었어도 그에 대한 접근(access)은 독립된 복사본인 클로저를 통해 이루어질 수 있다.
이제 Decorator를 이해할 준비가 끝났다.
Decorator
데코레이터 또한 하나의 기법이다.함수 앞 뒤에 기능을 추가할 수 있다!
그냥 코드를 봐보자
def deco_func(my_func):
def inner_func():
print('함수 앞 기능')
my_func()
print('함수 뒤 기능')
return inner_func
inner_func은 클로저 함수이다.
데코레이터를 사용하지 않았을 때의 경우는 아래 코드와 같다.
def deco_func(my_func):
def inner_func():
print('함수 앞 기능')
my_func()
print('함수 뒤 기능')
return inner_func
def star():
print('* * * * *')
no_deco = deco_func(star)
no_deco()

print(no_deco.__code__.co_freevars)

자유변수로 my_func을 받고 있음을 확인할 수 있다.
데코레이터를 적용해보자.
@deco_func
def star():
print('* * * * *')
star()


어렵지 않다..!
데코레이터 함수를 정의한 후
@를 사용해 데코레이터 함수명을 적어준 후
함수 앞 뒤 기능 사이에 실행할 함수를 정의하면 된다.
가변인자를 사용해서 모든 변수를 받을 수 있는 데코레이터는 아래와 같다.
(지난 글 참고(가변인자) : https://sso-y.tistory.com/11)
def decorator_all(function):
def inner_func(*args, **kwargs):
return '*' + function(*args, **kwargs) + '*'
return inner_func'Python > 파이썬 중급' 카테고리의 다른 글
| [Python] 네임드 튜플 (namedtuple) (0) | 2022.12.06 |
|---|---|
| [Python] 매직 메소드 (0) | 2022.11.30 |
| [Python] 데코레이터 심화 (0) | 2022.11.29 |
| [Python] 인스턴스 메소드, 클래스 메소드, 정적(static) 메소드 (0) | 2022.11.29 |
| [Python] __doc__ 메소드 (0) | 2022.11.29 |