Python — 데코레이터(decorator) 작성법

CianJS
5 min readMar 31, 2018

--

몇일 전 처음으로 파이썬에서의 데코레이터를 사용해보았습니다…

이렇게 한 언어에 대해서 깊게(?) 파보게 된 것은 처음인것같네요..
그런데 제가 파이썬으로 코딩하며 살고 있는 와중에 어떤 분이 제 코드를 보고 그러시더군요.

“여기서 어노테이션을 사용한 이유가 뭐야?”

저는 그때 처음 ‘어노테이션’이라는 단어를 들어보았습니다.
찾아보니 python의 데코레이터처럼 @을 사용한다는 것을 알게 되었습니다.
지금 생각해보면 그 분이 자바만 사용해오던 분이라서 어노테이션이라고 말씀하셨던 것일 수도 있다고 생각이 드네요..

제가 이번에 데코레이터 사용법에 대해서 포스팅을 하게 된 이유는 어노테이션(annotation)이란 것을 처음 들어서 데코레이터와 어노테이션의 차이가 궁금했기 때문입니다.

다음글에는 어노테이션이 무엇인지 간단하게 정의를 내려보고 데코레이터와 어노테이션의 차이에 대해서 다뤄보겠습니다.

먼저 이 글을 보시는 분들은 주로 데코레이터를 처음 접하셨거나 개념은 알지만 오랜만에 python을 다루게 되어 잊어버린 사용법을 알기 위해서 일 것이라 생각하니 바로 decorator의 사용법으로 가겠습니다만, 그 전에 간단한 정의를 알려드리겠습니다.

Decorator는 영어사전으로 찾아보면 ‘장식하는 사람' 또는 ‘장식’입니다.

이에 대해서는 다른 사람들과 이야기를 나눠본적이 없어서 잘 모르지만,
decorator라는 이름이 붙은 저의 생각을 말하자면,

화가의 그림(Main 기능)에 조명, 액자 등(추가 기능)을 통해 더욱 그 그림이 돋보이게 한다.

저는 이 Decorator를 이렇게 간단하게 정의해보았습니다.

왜 그런 것인지는 아래로 가시면서 같이 데코레이터를 사용해보면서 알아보도록 하겠습니다.

  1. 데코레이터(Decorator)의 구조

먼저 데코레이터를 사용하기전에 데코레이터를 사용하기 위한 구조(방법)가 4가지가 있다고 알려드리겠습니다.

데코레이터(Decorator)는 호출할 함수를 다른 함수에 매개변수로 전달한 후에 호출할 함수를 감싸는 함수(wrapper)에서 전달받은 함수를 이용하여 추가 작업을 한 후에 반환한다.’

말로 데코레이터의 기본 구조를 설명하면 위와 같습니다.
하지만 말로만으로는 잘 이해가 안가는 부분도 있으실거라 생각합니다.

python의 데코레이터는 함수형 2가지, class형 2가지 총 4가지 방식을 통해 작성할 수 있습니다.

1. 함수형 decorator(데코레이터에 인수 전달이 없는 경우 X)

데코레이터에 인수 전달이 없는 경우가 무엇인지는 2.에가서 이것이 무엇을 의미하는지 전달해드리도록 하겠습니다.)

작성 순서는 아래와 같습니다.

1) main 함수 제작(Decorator함수에 끌려갈 함수)

2) Decorator 함수에 전달받을 함수 넘기기 & Decorator 함수 안에 main 함수를 매개변수로 갖는 함수 제작(wrapper라고 주로 부름)

3) wrapper에서 전달받은 main 함수를 호출 or return(사용자 마음대로)

4) Decorator함수(wrapper 함수와 같은 위치)에서 wrapper를 return

첫번째 방식은 위와 같습니다만.. 코드의 경우 github 링크를 통해 봐주시면 감사하겠습니다.

그 다음은 decorator에 인수전달이 있는 경우입니다.

2. 함수형 decorator(데코레이터에 인수 전달이 있는 경우 O)

데코레이터에 인수 전달이 없는 경우가 무엇인지는 2.에가서 이것이 무엇을 의미하는지 전달해드리도록 하겠습니다.)

작성 순서는 아래와 같습니다.

1) main 함수 제작(Decorator함수를 먼저 작성해도 상관 없음.)

2) Decorator 함수 제작 인수 전달이 있는 경우엔 main 함수가 아니라 decorator의 매개변수를 먼저 불러옴.(decortator의 변수 지정)

3) decorator 안에 진짜 데코레이터(1.의 구조와같음) 구현
real_deco에서 main함수를 매개변수로 전달받는다.

4) real_deco의 안에 wrapper 생성(wrapper에서 function(main)의 매개변수를 받음.

5) real_deco에서 wrapper를 반환하고 가장 바깥의 main_deco에서 real_deco를 리턴한다.

link

3. Class 형 decorator(데코레이터에 인수가 없는 경우 X)

1) __init__메서드에 main함수(호출할 함수) 저장, self.function = function

2) __call__(인스턴스를 함수 호출처럼 사용가능하게 만들어줌.)메서드에 호출할 함수의 매개변수를 넘긴다.

3) 메인함수에 매개변수를 넣어서 호출하는 형태로 return

4. Class 형 decorator(데코레이터에 인수가 있는 경우 O)

1) __init__메서드에 decorator의 인수 저장

2) __call__ 메서드에 호출할 함수를 전달한다.

3) 메인함수에 매개변수를 넣어서 호출하는 형태로 return

4) __call__메서드에 wrapper 함수 생성 후 wrapper에 매개변수 전달

5) wrapper 함수에서 전달받은 함수 return

6) __call__ 메서드의 리턴을 return wrapper(매개변수)과 같은 형식으로 한다.

음.. 우선은 decorator를 작성하는 방법은 위의 4가지와 같습니다만..

역시 Medium은 글쓰기는 좋지만 코드는 전혀 좋지가 않네요.. ㅠㅠ
원래 이곳에 코드를 넣으려고 생각했었습니다만.. github로 대체하겠습니다.

그럼 다음은 코드가 없고 python의 decorator와 annotation의 차이점에 대해 글로만 정의를 해둔 글에서 찾아뵙겠습니다.

Decorator github: link

--

--

CianJS
CianJS

Written by CianJS

영어랑 영문서 자유롭게 듣고 읽고 싶다..

No responses yet