28.TIL (python-Decorator)

dream.log·2021년 7월 29일
0

TIL

목록 보기
27/42
post-thumbnail

오늘은 파이썬의 decorator 개념에 대해 공부해보자!

파이썬에서 함수를 장식하는 것!을 데코레이터라고 할 수 있다.
@ 를 통해 사용하며, 이미 완성된 함수에 함수를 수정하지 않고 추가 기능을 구현할 때 사용한다. 데코레이터는 ['장식자'] 라고 불리기도 한다.

1. 데코레이터의 기본 형태

@ decorator
def 함수 이름():
	코드 

🔆 매개변수와 반환값이 없는 함수 데코레이터 만들기

def trace(func):		# 호출할 함수를 매개변수로 받음 
	def wrapper():		# 호출할 함수를 감싸는 함수
		print (func.__name__,'함수시작')  # __.name.__ 을 통해 이름 입력
		func()		   # 함수 호출
		print (func.__name__,'함수끝')	  
	return wrapper	  	   # wrapper 함수 반환 

trace_hello = trace(hello)	# 데코레이터에 호출할 함수 넣음
trace_hello()				# 반환된 함수를 호출

@ trace   # 데코레이터 사용
def hello(): # 함수로 호출한 hello가 상단 trace 함수 func() 자리에 들어감
	print ('hello')

hello()  # 함수 그대로 출력

중첩함수 (함수안의 함수)를 정의해준 후, @ 를 활용해 함수의 이름을 불러주고, print하면
상단의 trace 함수의 로직을 통해 다음과 같은 문구가 출력된다.

hello 함수 시작
hello
hello 함수 끝

데코레이터는 여러개 적용도 가능하나, 위에서 아래 순으로 실행된다.

🔆 매개변수와 반환값을 처리하는 함수 데코레이터 만들기

def practice(func):		
	def pracWrapper(a,b): # 호출할 함수 add(a,b)의 매개변수와 똑같이 지정
		r = func(a,b)	  # func에 매개변수 a,b를 넣어서 호출하고 반환값에 저장
		print('{0}(a={1},b={2}) -> {3}.' .format(func.__name__,a,b,r)) # 매개 변수와 변환값 출력
		return r # func값 반환
	return pracWrapper 	# pracWrapper 값 반환

@practice		# @ 데코레이터 사용
def add(a,b):  		# 두개의 변수가 있다.
	return a + b  # a와 b를 더해라!

print(add(10,20))		

pracWrapper 함수에서 return r 해주지 않으면 add 함수를 호출해도 반환 값이 나오지 않기 때문에 해당 부분을 유의해야 한다.

✔️ 만약, func의 반환값을 출력할 필요가 없다면?
: return func(a,b) 의 형태로 바로 함수를 호출하고 반환해도 된다.

🔆 매개변수가 고정되지 않은 함수 처리하기

def notFix(func):
	def Wrapper(*args, **kwargs): # 가변인수함수로 만들어준다. 
		r = func(*args, **kwargs) # func에 args, kwargs를 넣어준다
		print('{0}(args={1}, kwargs={2})-> {3}'.format(func.__name__, args,kwargs,r)) # 매개변수의 반환값을 출력한다

		return r 	# func의 반환값을 반환
	return Wrapper	# Wrapper함수 반환

@notFix 	 		# 데코레이터 사용하기
def get_Max(*args)  # 위치 인수를 사용하는 가변인수 함수
	return Max(args) 

@notFix
def get_Min(**kwargs):	# 키워드 인수를 사용하는 가변인수 함수
	return Min(kwargs.values())

print(get_Max(10,20))			# 20 출력
print(get_Min(x=10,y=30, z=50)) # 10 출력	

하단에 만들어준 get_Max ,get_Min 함수는 각각 가변 인수 함수이므로, 데코레이터도 가변 인수 함수로 만들어야 한다.
위치 인수와 키워드 인수 모두를 받을 수 있도록 args, kwargs를 지정해주어야 한다.

args는 튜플, kwargs는 딕셔너리 형태로 출력이 된다.
그러므로, func에 넣을 때는 언패킹 해서 넣어야 한다!

이렇게 만든다면, 가변함수가 아닌 일반 함수에도 데코레이터 사용이 가능하다 -!

2. 클래스에 데코레이터 만들기

다음은, 클래스에 데코레이터를 만드는 방법이다.
이 방법을 잘 익혀야 현재 짜고 있는 View에 데코레이터를 적용할 수 있다!!!!!!!!!

🔆 함수의 시작과 끝을 출력하는 데코레이터 - class.ver

class Trace:
	def __init__(self,func): # 호출할 함수를 인스턴스의 초깃값으로 받음
		self.func = func	 # 호출할 함수를 속성 func에 저장

	def __call__(self):		# 인스턴스를 호출하기 위해 만듬
		print(self.func.__name__,'함수 시작')  # __name__으로 함수 이름 출력
		self.func()			# 속성 func에 저장된 함수 호출
		print(self.func.__name__,'함수 끝')

@Trace
def hello():
	print('hello')

hello()	# 함수 그대로 호출		

먼저 __init__ method를 만들어 호출할 함수를 초깃값으로 받는다.그리고 매개변수로 받은 함수를 속성으로 저장한다. 인스턴스를 다시 호출하기 위해 __call__ 을 사용해준다! __call__ method에서는 함수의 시작을 알리는 문자와 끝을 알리는 문자열을 여기서는 출력해주었다.

클래스로 만든 데코레이터는 @ 지정없이 데코레이터의 반환값을 호출하는 형식으로도 사용할 수 있다. 데코레이터에 호출할 함수를 넣어 인스턴스를 만들고 그 인스턴스를 호출한다! 클래스에서 이미 정의한 내용이므로 함수처럼 ()로 출력이 가능한 것이다!

def hello():
	print('hello')
    
trace_hello = Trace(hello) # Trace 클래스에 hello 함수를 넣어 호출한다!
trace_hello

🔆 매개변수와 반환값을 처리하는 데코레이터 만들기 - class.ver

class Trace:
    def __init__(self, func):    
        self.func = func         
 
    def __call__(self, *args, **kwargs):    # 호출할 함수의 매개변수를 처리
        r = self.func(*args, **kwargs) # self.func에 매개변수를 넣어서 호출하고 반환값을 변수에 저장
        print('{0}(args={1}, kwargs={2}) -> {3}'.format(self.func.__name__, args, kwargs, r))
                                            # 매개변수와 반환값 출력
        return r                            # self.func의 반환값을 반환
 
@Trace    # @데코레이터
def add(a, b):
    return a + b
 
print(add(10, 20))
print(add(a=10, b=20))

__call__ 메서드에 매개변수를 저장하고, self, func에 매개변수를 넣어서 호출한 뒤 반환값을 반환해주는 형태이다. 매개변수를 args, kwargs로 넣었으므로, self, func에 넣을 때는 언패킹해서 넣어야 한다.(args 튜플, kwargs 딕셔너리)

🙅🏻‍♀️ 자꾸 혼동하는 기초 개념!
[class , method, instance, object]

class Food: 
	def koreanfood(self): 
    	return "맛있다!"
        
   bulgogi = Food()
   bulgogi.koreanfood()

❕ 함수를 풀어서 설명해보자면,
koreanfood 함수는 class가 할 행동을 정의하고 있다.
함수를 만든 후에는 bulgogi라는 객체를 만들었다.
bulgogi라는 객체에 .을 찍어 메서드를 불러온다!

  • Method : 클래스 내부에 정의된 함수 (koreanfood)

  • object(객체), instance(인스턴스) : bulgogi
    instance : 클래스에 의해 만들어진 객체

  • 객체와 인스턴스는 비슷한 의미이나, 인스턴스는 특정 객체가 어떤 클래스의 객체인지 관계 위주로 설명할 때 사용한다.
    객체에는 정의해놓은 함수내용이 실제로 적용되며, 프로그램에서 구현할 대상이 된다.
    클래스에 만들어진 객체들은 각각의 독립적인 특성을 띄고 있다.
    인스턴스는 메모리에 할당되어, 실제 사용될 때 인스턴스가 된다. 인스턴스를 객체에 포함되며, 객체 지향 프로그래밍은 객체를 중심으로 프로그래밍 한다는 의미!

    ex) class : 자동차의 설계도, 객체 : 만들어진 자동차.
    트럭은 객체이며, 자동차의 인스턴스이다.

    ex) 자주쓰고 있는 예시
    user.object.get(email=data['email'])
    : user의 객체의 get method를 활용해 user의 email data를 불러온다!


🟡 출처 :

profile
한 걸음, 한 걸음 포기하지 않고 발전하는 Backend-developer 👩🏻‍💻 노션 페이지를 통한 취업 준비 기록과 회고를 진행하고 있습니다. 계획과 기록의 힘을 믿고, 실천하고자 합니다.

0개의 댓글