데코레이터 프로그래머가 함수나 클래스의 동작을 수정할 수 있도록 하기 때문에 Python의 매우 강력하고 유용한 도구입니다. 데코레이터를 사용하면 래핑된 함수를 영구적으로 수정하지 않고도 래핑된 함수의 동작을 확장하기 위해 다른 함수를 래핑할 수 있습니다. 하지만 데코레이터에 대해 자세히 알아보기 전에 데코레이터를 학습하는 데 도움이 되는 몇 가지 개념을 이해해 보겠습니다.
일류 개체
파이썬에서 함수는 일류 물건 이는 Python의 함수를 인수로 사용하거나 전달할 수 있음을 의미합니다.
일급 함수의 속성:
- 함수는 객체 유형의 인스턴스입니다.
- 함수를 변수에 저장할 수 있습니다.
- 함수를 다른 함수에 매개변수로 전달할 수 있습니다.
- 함수에서 함수를 반환할 수 있습니다.
- 해시 테이블, 목록 등과 같은 데이터 구조에 저장할 수 있습니다.
더 나은 이해를 위해 아래 예를 고려하십시오.
예시 1: 함수를 객체로 취급합니다.
파이썬3
# Python program to illustrate functions> # can be treated as objects> def> shout(text):> >return> text.upper()> print>(shout(>'Hello'>))> yell>=> shout> print>(yell(>'Hello'>))> |
>
>
산출:
HELLO HELLO>
위의 예에서는shout 함수를 변수에 할당했습니다. 이것은 함수를 호출하지 않고 대신 외침에 의해 참조되는 함수 개체를 가져와 이를 가리키는 두 번째 이름인 소리를 만듭니다.
예 2: 함수를 인수로 전달하기
파이썬3
# Python program to illustrate functions> # can be passed as arguments to other functions> def> shout(text):> >return> text.upper()> def> whisper(text):> >return> text.lower()> def> greet(func):> ># storing the function in a variable> >greeting>=> func(>'''Hi, I am created by a function passed as an argument.'''>)> >print> (greeting)> greet(shout)> greet(whisper)> |
>
>
산출:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
위의 예에서 Greeting 함수는 또 다른 함수를 매개변수로 사용합니다(이 경우에는 소리치기와 속삭임). 인수로 전달된 함수는 Greeting 함수 내에서 호출됩니다.
예시 3: 다른 함수에서 함수를 반환합니다.
파이썬3
SQL의 대소 문자는 무엇입니까
# Python program to illustrate functions> # Functions can return another function> def> create_adder(x):> >def> adder(y):> >return> x>+>y> >return> adder> add_15>=> create_adder(>15>)> print>(add_15(>10>))> |
>
>
산출:
25>
위의 예에서는 다른 함수 내부에 함수를 생성한 다음 내부에서 생성된 함수를 반환했습니다.
위의 세 가지 예는 데코레이터를 이해하는 데 필요한 중요한 개념을 설명합니다. 이를 살펴본 후 이제 데코레이터에 대해 자세히 살펴보겠습니다.
데코레이터
위에서 언급했듯이 데코레이터는 함수나 클래스의 동작을 수정하는 데 사용됩니다. 데코레이터에서 함수는 다른 함수의 인수로 사용된 다음 래퍼 함수 내에서 호출됩니다.
데코레이터 구문:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''> 위의 코드에서 gfg_ decorator는 호출 가능한 함수로, 다른 호출 가능한 함수인 hello_decorator 함수 위에 일부 코드를 추가하고 래퍼 함수를 반환합니다.
데코레이터는 행동 :
파이썬3
# defining a decorator> def> hello_decorator(func):> ># inner1 is a Wrapper function in> ># which the argument is called> > ># inner function can access the outer local> ># functions like in this case 'func'> >def> inner1():> >print>(>'Hello, this is before function execution'>)> ># calling the actual function now> ># inside the wrapper function.> >func()> >print>(>'This is after function execution'>)> > >return> inner1> # defining a function, to be called inside wrapper> def> function_to_be_used():> >print>(>'This is inside the function !!'>)> # passing 'function_to_be_used' inside the> # decorator to control its behaviour> function_to_be_used>=> hello_decorator(function_to_be_used)> # calling the function> function_to_be_used()> |
>
>
산출:
Hello, this is before function execution This is inside the function !! This is after function execution>
위 코드의 동작과 function_to_be_used가 호출될 때 단계별로 어떻게 실행되는지 살펴보겠습니다.

쉽게 알 수 있는 또 다른 예로 넘어가겠습니다. 함수의 실행 시간 데코레이터를 사용합니다.
파이썬3
# importing libraries> import> time> import> math> # decorator to calculate duration> # taken by any function.> def> calculate_time(func):> > ># added arguments inside the inner1,> ># if function takes any arguments,> ># can be added like this.> >def> inner1(>*>args,>*>*>kwargs):> ># storing time before function execution> >begin>=> time.time()> > >func(>*>args,>*>*>kwargs)> ># storing time after function execution> >end>=> time.time()> >print>(>'Total time taken in : '>, func.__name__, end>-> begin)> >return> inner1> # this can be added to any function present,> # in this case to calculate a factorial> @calculate_time> def> factorial(num):> ># sleep 2 seconds because it takes very less time> ># so that you can see the actual difference> >time.sleep(>2>)> >print>(math.factorial(num))> # calling the function.> factorial(>10>)> |
>
>
산출:
3628800 Total time taken in : factorial 2.0061802864074707>
함수가 무언가를 반환하거나 인수가 함수에 전달되면 어떻게 되나요?
위의 모든 예에서 함수는 아무것도 반환하지 않았으므로 문제가 없었지만 반환된 값이 필요할 수 있습니다.
파이썬3
def> hello_decorator(func):> >def> inner1(>*>args,>*>*>kwargs):> > >print>(>'before Execution'>)> > ># getting the returned value> >returned_value>=> func(>*>args,>*>*>kwargs)> >print>(>'after Execution'>)> > ># returning the value to the original frame> >return> returned_value> > >return> inner1> # adding decorator to the function> @hello_decorator> def> sum_two_numbers(a, b):> >print>(>'Inside the function'>)> >return> a>+> b> a, b>=> 1>,>2> # getting the value through return of the function> print>(>'Sum ='>, sum_two_numbers(a, b))> |
>
자바 변수 변수
>
산출:
before Execution Inside the function after Execution Sum = 3>
위의 예에서 내부 함수의 매개변수에 큰 차이가 있음을 알 수 있습니다. 내부 함수는 인수를 *args 및 **kwargs로 사용합니다. 이는 위치 인수 튜플이나 키워드 인수 사전이 어떤 길이로도 전달될 수 있음을 의미합니다. 이는 임의 개수의 인수를 갖는 함수를 장식할 수 있는 일반 장식자가 됩니다.
체인 데코레이터
간단히 말해서 데코레이터를 연결한다는 것은 여러 데코레이터로 함수를 꾸미는 것을 의미합니다.
예:
파이썬3
# code for testing decorator chaining> def> decor1(func):> >def> inner():> >x>=> func()> >return> x>*> x> >return> inner> def> decor(func):> >def> inner():> >x>=> func()> >return> 2> *> x> >return> inner> @decor1> @decor> def> num():> >return> 10> @decor> @decor1> def> num2():> >return> 10> > print>(num())> print>(num2())> |
>
>
산출:
400 200>
위의 예는 다음과 같이 함수를 호출하는 것과 유사합니다.
decor1(decor(num)) decor(decor1(num2))>