Python의 함수는 일급 객체라는 특성 상, Decorator
라는 문법을 이용해 특정 함수에 미리 만들어 둔 함수를 전달해 기능을 추가할 수도 있습니다. Python 2.4에서 추가되었고, PEP 318에서 확인해볼 수 있습니다. 간단하게, 함수가 호출되기 전에 '함수가 실행됩니다'라는 문자열을 출력해 봅시다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def decorator(fn): | |
def wrapper(): | |
print('함수가 실행됩니다.') | |
return fn() | |
return wrapper | |
def print_hello(): | |
print('hello') | |
decorated_print_hello = decorator(print_hello) | |
decorated_print_hello() | |
# '함수가 실행됩니다.' | |
# 'hello' |
천천히 살펴봅시다.
decorator
함수는 인자로 fn이라는 함수를 받습니다.decorator
함수는 '함수가 실행됩니다.'라는 문자열을 출력하며 fn을 호출하고 그 결과를 반환하는 내부 함수wrapper
를 가지고 있습니다.decorator
함수는 내부 함수인wrapper
를 리턴합니다.
wrapper
함수는 클로저로 인해 decorator
함수가 가진 지역변수 fn에 접근할 수 있게 됩니다. 그럼 코드의 흐름을 살펴 봅시다.
decorator
함수에 'hello'라는 문자열을 출력하는print_hello
함수를 전달했습니다.decorator
함수는wrapper
함수를 리턴합니다. 이를decorated_print_hello
라는 변수에 할당했습니다.- 해당 변수의 타입은 함수이므로, 그대로 호출하면
wrapper
함수가 호출되며 '함수가 실행됩니다.'라는 문자열이 출력되고, 전달했던print_hello
함수가 호출되어 'hello'까지 출력되었습니다.
Decorator expression
일반적으로 위와 같이 함수를 넘겨주고, 함수를 받고, 그걸 다시 실행하는 복잡한 구조는 잘 사용하지 않습니다. Python은 데코레이터를 쉽게 사용할 수 있도록 @
심볼을 제공하며, 이 부분은 Java의 어노테이션과 비슷합니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def decorator(fn): | |
def wrapper(): | |
print('함수가 실행됩니다.') | |
fn() | |
return wrapper | |
@decorator | |
def print_hello(): | |
print('hello') | |
print_hello() | |
# '함수가 실행됩니다.' | |
# 'hello' |
인자가 있는 함수 데코레이팅하기
인자를 가진 함수를 데코레이팅하고 싶다면, 내부(wrapper) 함수에 *args와 **kwargs를 추가하면 됩니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def decorator(fn): | |
def wrapper(*args, **kwargs): | |
print('함수가 실행됩니다.') | |
fn(*args, **kwargs) | |
return wrapper | |
@decorator | |
def sum(a, b): | |
return a + b | |
print(sum(1, 3)) | |
# '함수가 실행됩니다.' | |
# 4 |
여기서 wrapper 함수는 데코레이팅과 함께 인자를 중계해주는 형태입니다.
'Python 계열 > Python 레거시 글' 카테고리의 다른 글
[Python] Generator (0) | 2018.07.23 |
---|---|
[Python] Iterable, Sequence, Iterator (0) | 2018.07.22 |
[Python] Closure (0) | 2018.07.20 |
[Python] 문자열의 메모리 할당 방식 (0) | 2018.07.19 |
[Python] 함수 인자의 기본값 평가 (0) | 2018.07.14 |