장식물을 달아준다는 의미이다. 먼저 장식물이 없는 함수콜은 아래와 같다.일반 코드를 쓰면 아래와 같다.
def hello():
print('hello~~')
hello()
-----------------------------------------------------------
hello~~
함수를 매개변수로 가지는 함수를 정의해서 윗 함수를 호출해보자
def test(func):
print('인사의 시작')
func()
print('인사의 종료')
def hello():
print('hello by normal function call')
test(hello)
이번엔 @데코레이터를 사용해보자.
def test(func):
def wrapper():
print('인사의 시작')
func()
print('인사의 종료')
return wrapper
@test
def hello():
print('hello by decorator')
hello()
사용법이 조금 복잡하다.
그래서 아래와 같이 설명을 적어서 이해해 보도록 노력했다.
def test(func): # 함수(hello)를 func라는 이름으로 받음
def wrapper(): # func를 감쌀 '새로운 함수'를 정의
print('인사의 시작') # 머릿글 추가
func() # 여기서 진짜 hello()가 실행됨
print('인사의 종료') #꼬릿글 추가
return wrapper # 새로 만든 보자기(wrapper)를 반환
@test # 이제 아래에 정의되는 함수는 test라는 감옥에 갇힌다는 뜻임.
def hello():
print('hello by decorator')
hello() # test라는 감옥에 갇힌 hello다.
# 그 결과: 인사 시작 -> hello -> 인사 종료
그럼 @데코레이터 이게 왜 좋은가?
- @데코레이터를 사용하면 hello()만 호출해도 됨. test(hello) 할 필요가 없음. 즉, hello의 성격이 바뀌었다.
- @데코레이터를 여러 함수에 적용할 수 있다. 게시판에 글을 쓰거나 수정하려면 로그인했느지 여부를 체크하는 루틴이 꼭 들어가야 하는데 이 때 글쓰기, 수정 함수를 정의 할 때, 정의 문 앞에 @login 이라는 데코레이터를 달아주면 post(), update() 함수를 그대로 사용할 수 있다.
@를 감옥이라고 표현한 이유
어린왕자를 보면 모자 형태를 보고 “코끼리를 삼킨 보아뱀”이라는 글이 있다. 본인은 @가 새장에 같힌 앵무새같이 보인다. 그래서 파이썬의 @데코레이터를 배울 때 함수를 새장과 같은 감옥에 가두는 느낌이 들었다.