ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코딩도장] day28. 파이썬 데코레이터(1/2) - @데코레이터, def데코레이터
    IT/파이썬 2020. 9. 22. 00:02

    출처 : unsplash

     

    ■ 들어가기

    - 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그


    ▶ Unit42. 데코레이터 사용하기

         - 42.1 데코레이터 만들기

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

         - 42.3 매개변수가 있는 데코레이터 만들기

         - 42.4 클래스로 데코레이터 만들기

         - 42.5 클래스로 매개변수와 반환값을 처리하는 데코레이터 만들기

     

     

    0. 들어가기

    - 데코레이터(decorator) : 클래스 내 메서드를 장식하는 도구 (표기: @)

    - 사용예시

    class Calc :

        @staticmethod   # 데코레이터

        def add(a, b) :

            print(a + b)

     

     

    >> 42.1 데코레이터 만들기 <<

    - 데코레이터는 함수를 수정하지 않은 상태에서 추가 기능 구현 시 사용

    - 예제 : 함수 시작, 끝을 출력하는 기능 구현

    설명 : 일반적인 함수 작성
    소스 (function_begin_end.py) 결과
    def hello() :
        print('hello 함수 시작')
        print('hello')
        print('hello 함수 끝')

    def world() :
        print('world 함수 시작')
        print('world')
        print('world 함수 끝')

    hello()
    world()
    hello 함수 시작
    hello
    hello 함수 끝
    world 함수 시작
    world
    world 함수 끝

     

    설명 : 데코레이터를 활용한 함수  
    소스 (decorator_closure.py) 결과
    def trace(func) :                           # 호출할 함수를 매개변수로 받음
        def wrapper() :                         # 호출할 함수를 감싸는 함수
            print(func.__name__, '함수 시작')   # __name__으로 함수 이름 출력
            func()                              # 매개변수로 받은 함수를 호출
            print(func.__name__, '함수 끝')
        return wrapper                          # wrapper 함수 반환

    def hello() :
        print('hello')

    def world() :
        print('world')

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

     

    1. @으로 데코레이터 사용하기

    - 사용법

    @데코레이터

    def 함수이름() :

        코드

    소스 (decorator_closure_at_sign.py) 결과
    def trace(func) :   # 호출할 함수를 매개변수로 받음
        def wrapper() :
            print(func.__name__, '함수 시작')   # __name__으로 함수 이름 출력
            func()                              # 매개변수로 받은 함수를 호출
            print(func.__name__, '함수 끝')
        return wrapper

    @trace  # @데코레이터
    def hello() :
        print('hello')

    @trace  # @데코레이터
    def world() :
        print('world')

    hello()     # 함수를 그대로 호출
    world()     # 함수를 그대로 호출
    hello 함수 시작
    hello
    hello 함수 끝
    world 함수 시작
    world
    world 함수 끝

    출처 : 파이썬 코딩 도장 (dojang.io)

    - 그러면 trace라는 함수말고 다른 이름의 함수 만들고 해당 함수 이름으로 @ 데코레이터 붙히면 어떻게 될까??

    - 결론 : 된다!!!! // 데코레이터 이름의 함수를 만들고 데코레이터로 호출하면 처리 가능하구나!! 그렇지 않으면 NameError 발생!

    소스 (decorator_closure_at_sign2.py) 결과
    def abc(func) :   # 호출할 함수를 매개변수로 받음
        def wrapper() :
            print(func.__name__, '함수 시작')   # __name__으로 함수 이름 출력
            func()                              # 매개변수로 받은 함수를 호출
            print(func.__name__, '함수 끝')
        return wrapper

    @abc  # @데코레이터
    def hello() :
        print('hello')

    @abc  # @데코레이터
    def world() :
        print('world')

    hello()     # 함수를 그대로 호출
    world()     # 함수를 그대로 호출
    hello 함수 시작
    hello
    hello 함수 끝
    world 함수 시작
    world
    world 함수 끝

     

     

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

    - 매개변수와 반환값을 처리하는 데코레이터 확인

    - 실제 호출할 함수의 매개변수와 wrapper 함수의 매개변수를 똑같이 만들어줌

    소스 (decorator_param_return.py) 결과
    def trace(func) :
        def wrapper(a, b) :
            r = func(a, b)
            print('{0}(a={1}, b={2}) -> {3}'.format(func.__name__, a, b, r))
            return r
        return wrapper

    @trace
    def add(a, b) :
        return a + b

    print(add(10, 20))
    add(a=10, b=20) -> 30
    30

     

     

    1. 가변 인수 함수 데코레이터

    - 매개변수(인수)가 고정되지 않은 함수 처리 방법은?

    -> wrapper 함수를 가변 인수 함수로 만들면 된다.

    소스 (decorator_variable_argument.py) 결과
    def trace(func) :   # 호출할 함수를 매개변수로 받음
        def wrapper(*args, **kwargs) :  # 가변 인수 함수로 만듦
            r = func(*args, **kwargs)   # func에 args, kwrargs를 언패킹하여 넣어줌
            print('{0}(args={1}, kwargs={2}) -> {3}'.format(func.__name__, args, kwargs, r)) # 매개변수와 반환값 출력
            return r                    # func의 반환값을 반환
        return wrapper                  # wrapper 함수 반환

    @trace  # @데코레이터
    def get_max(*args) :    # 위치 인수를 사용하는 가변 인수 함수
        return max(args)

    @trace  # @데코레이터
    def get_min(**kwargs) : # 키워드 인수를 사용하는 가변 인수 함수
        return min(kwargs.values())

    print(get_max(10, 20))
    print(get_min(x=10, y=20, z=30))
    get_max(args=(10, 20), kwargs={}) -> 20
    20
    get_min(args=(), kwargs={'x': 10, 'y': 20, 'z': 30}) -> 10
    10

    - get_max, get_min 함수는 가변 인수 함수로써, get_max 함수는 튜플로, get_min 함수는 딕셔너리(key-value)로 데이터 전달

    - args 는 튜플, kwargs는 딕셔너리

     

     

    댓글

Designed by Tistory.