시작하기 전에
데코레이터란 flask로 앱을 시작할때 ' @app.route('/')' 이 부분에 대한 것이다.
함수에서 함수자체를 인자로 받아서 명령을 실행한 뒤 다시 함수의 형태로 반환하는 경우이다.
보통 함수의 내부를 수정하지 않고, 기능에 변화를 주고 싶을 때 사용한다.
데코레이터를 이해하기에 앞서 연관된 개념인 first class 함수와, closure에 대해서 먼저 정리해보고자 한다.
중첩 함수 (Nested function)
: 함수 내부에 또 다른 함수가 정의된 것이다.
: 중첩함수/ closure 두가지 개념이 중첩함수와 관련되어 있다.
1
2
3
4
5
6
7
8
9
10
|
def outer_func(num):
def inner_func():
print(num)
return 'a'
return inner_func
fn = outer_func(10)
print(fn())
|
cs |
-> 여기서 inner_func이 중첩함수이다.
# 중첩함수는 함수 밖에서는 호출 불가 (outer_func 함수 안에서 선언되었으니, outer_func 함수 안에서만 호출 가능)
First-class function
-
함수 자체를 변수에 저장 가능
-
함수의 인자에 다른 함수를 인수로 전달 가능
-
함수의 반환 값(return 값)으로 함수를 전달 가능
이는 파이썬이 객체지향적언어이기 때문이며, 따라서 비슷한 성격의 언어들은 First-class 함수를 지원한다.
python, Go, javascript, Kotlin 은 First-class 함수 지원
C 언어등은 First-class 함수 미지원
Closure function
- First-class 함수와 유사한 개념
- 외부함수의 인자에 대해 내부함수가 접근할 수 있는 것
- 내부함수에서 외부함수의 인자를 사용하고 있으면 closure의 개념을 활용한 것이라고 이해하면 된다.
1
2
3
4
5
6
7
|
def outer_func(num):
def inner_func():
print(num)
return '안녕'
return inner_func
|
cs |
->위의 예제에서 inner_func이 바로 closure 임
-> outer_func(10) 호출 종료시 num 값은 없어졌으나, closure_func()으로써 inner_func이 호출되면서 이전의 num값(10)을 사용함
데코레이터 (Decorator)
: 위에서 설명한 중첩함수로써, 외부함수의 인자가 함수이고, 그 내부함수에서 클로저로써 이 함수인자를 사용하는 경우 활용된다.
: 다음과 같이 @decorator_func 부분이 데코레이터이다.
1
2
3
4
5
6
7
|
# 데코레이터 작성하기
def datetime_decorator(func): # <--- datetime_decorator 는 데코레이터 이름,
def wrapper(): # <--- 호출할 함수를 감싸는 함수
print ('time ' + str(datetime.datetime.now())) # <--- 함수 앞에서 실행할 내용
func() # <--- 함수
print (datetime.datetime.now()) # <--- 함수 뒤에서 실행할 내용
return wrapper # <--- closure 함수로 만든다.
|
cs |
-> 데코레이터 적용 후,
1
2
3
4
5
6
|
# 데코레이터 적용하기
@datetime_decorator # @데코레이터
def logger_login_david():
print ("David login")
logger_login_david()
|
cs |
-> 즉 반복될 함수와 그 안에 인자로 들어갈 함수의 코드 작성 및 관계 이해가 좀 더 용이하다.
-> 위의 예시에서 logger_login_david() 가 datetime_decorator( )의 함수인자인 셈이다.
내부함수에 별도의 변수가 있는 함수에 Decorator 적용하기
1
2
3
4
5
6
7
8
|
# 데코레이터
def outer_func(function):
def inner_func(digit1, digit2):
if digit2 == 0:
print('cannot be divided with zero')
return
function(digit1, digit2)
return inner_func
|
cs |
1
2
3
4
|
# 데코레이터 사용하기 (유효성 검사)
@outer_func
def divide(digit1, digit2):
print (digit1 / digit2)
|
cs |
->외부함수는 함수인자를 받고, 내부함수가 변수를 인자로 받는 경우, 데코레이터 함수와
인자함수 코드를 작성할때, 인자 함수에 내부함수의 변수를 넣어서 기재하면된다.
내부함수의 변수가 정해지지 않은 경우 Decorator 만들기
->이는 자바스크립트의 spread parameter을 떠올리면 쉽다
->정해지지 않은 인자를 표현하고 싶을 때는 (args, **kwargs) 로 표현 가능
한 함수에 데코레이터 여러 개 지정하기
- 함수에 여러 개의 데코레이터 지정 가능 (여러 줄로 @데코레이터를 써주면 됨)
- 데코레이터를 나열한 순서대로 실행됨
Method Decorator
: 클래스의 method에도 데코레이터 적용 가능
1
2
3
4
5
|
# 데코레이터 작성하기 (for method)
def h1_tag(function):
def func_wrapper(self, *args, **kwargs):
# <--- self 를 무조건 첫 파라미터로 넣어야 메서드에 적용가능 return "<h1>{0}</h1>".format(function(self, *args, **kwargs))
# <--- function 함수에도 self 를 넣어야 함 return func_wrapper
|
cs |
1
2
3
4
5
6
7
8
9
|
# 클래스 선언시 메서드에 데코레이터 적용하기
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@h1_tag
def get_name(self):
return self.first_name + ' ' + self.last_name
|
cs |
-> h1_tag함수가 데코레이터 함수이며, get_name 함수가 h1_tag의 함수 인자이다.
그리고 get_name 인자함수는 person의 메소드인 init의 값을 사용하고 싶다.
이때 활용되는 것이 self 인 것이다.
외부함수에 변수인자가 파라미터인 Decorator 만들기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
def mark_html(tag):
def outer_wrapper(function):
def inner_wrapper(*args, **kwargs):
return '<' + tag + '>' + function(*args, **kwargs) + '</' + tag + '>'
return inner_wrapper
return outer_wrapper
@mark_html('b')
def print_bold(title):
return title
|
cs |
-> 위의 예제처럼 중첩을 한 번 더 진행하고, 데코레이터 함수를 실행할 때, 그 인자에 외부함수에 넣을 변수 인자를 넣으면 된다.
'SW Engineering > BE' 카테고리의 다른 글
Flask로 서버 구축하기_REST API(feat. 프론트) (0) | 2020.11.13 |
---|---|
Flask로 서버 구축하기_Routing기본 (0) | 2020.11.12 |
Flask 개발환경 설정하기(VSC 환경설정) (0) | 2020.11.10 |
파이썬 Flask 시작하기 / 기본 라우팅 설정 (0) | 2020.11.08 |
Node.js 설치하고 시작하기(수정) (0) | 2020.11.05 |