ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Python - 데코레이터
    개발 2023. 2. 14. 16:09

    Decorator

     

    파이썬에서는 함수에 데코레이터라는 기능을 추가할 수 있다. 함수가 실행 될 때 다른 함수를 타도록 만드는 기능이다. 

     

    def to_upper_text(func):
        text = func()
    
        if not isinstance(text, str):
            raise TypeError("not a string type")
    
        return text.upper()
    
    
    @to_upper_text
    def say():
        return "welcome"

     

    say 함수 위에 @to_upper_text 라는 데코레이터를 추가했다. 데코레이터 안에서는 전달 받은 func() 함수의 결과 값이 str인지 확인하고 아니면 에러를 호출, 맞으면 upper 함수를 호출해서 대문자로 리턴한다. 

     

    WELCOME

     

    실행하면 대문자로 바뀌어서 출력된다.

     

    def to_upper_case(func):
        def wrapper(*args, **kwargs):
            text = func(*args, **kwargs)
            if not isinstance(text, str):
                raise TypeError("not a string type")
            return text.upper()
    
        return wrapper

     

    일반적으로 데코레이터는 wrapper 함수랑 같이 사용한다. wrapper 함수를 사용해서 인자값을 넣고 이 안에 로직을 넣는다. 데코레이터 함수는 wrapper 함수를 리턴한다. 

     

    @to_upper_case
    def say2(text: str):
        return text
    
    print(say2("Hello World"))  # -> 함수랑 인자랑 같이 넘겨줌
    
    #################
    HELLO WORLD

     

    실행하면 전달받은 스트링값이 대문자로 변환돼서 HELLO WORLD가 출력된다. 

     

    def add_suffix(func):
        def wrapper(*args, **kwargs):
            text = func(*args, **kwargs)
            return "".join([text, " selfish-developer"])
    
        return wrapper
    
    
    @add_prefix
    @to_upper_case
    def say1():
        return "welcome"
        
        
    ###############
    WELCOME SELFISH-DEVELOPER

     

    데코레이터를 여러개 지정할 수 있다. add_suffix는 뒤에 selfish-developer 라는 스트링을 붙이는 작업이다. 출력결과 모든 문자가 대문자로 변환돼서 출력됐다. 데코레이터를 중첩해서 쓰는 경우 가장 아래있는 것부터 실행된다.

     

     

    Use Case

     

    데코레이터는 로깅이나, 에러 체크를 할 때 쓰면 유용하다. 서버상에서 특정 함수는 유저가 로그인이 된 상태에서만 실행하도록 만들고 싶은 경우 매번 함수 내에 같은 로직을 추가하는것보다는 데코레이터를 사용해서 작업을 통일할 수 있다.  

     

    def login_required(func):
        @wraps(func)
        def check_login(*args, **kwargs):
            if request.user is None:
                print(f"#### func: {func.__name__} user not logged in ####")
                raise "user is not logged in"
            return func(*args, **kwargs)
    
        return check_login
    
    
    @login_required
    def update_name(name: str, player_id: int) -> str:
        check_name(name)
    
        session = db.get_session()

     

    login_required 이용해서 유저의 로그인 유무를 확인하는 함수다. request 인자에 user 가 None이 아니면 로그인이 된것으로 보고 원래 함수를 타게하고 그렇지 않으면 raise를 두도록 했다. 아래 이름을 업데이트 하는 코드는 로그인이 됐을 때만 실행해야 하므로 함수 데코레이터를 사용해서 처리했다. 데코레이터만 추가하면 매번 user 로그인 유무를 확인하지 않아도 되기 때문에 유용하다.

    '개발' 카테고리의 다른 글

    Python - namedtuple  (0) 2023.02.14
    Python - 제너레이터  (0) 2023.02.14
    Nodejs Blocking/Non-Blocking,  (0) 2023.01.26
    socketio redis adapter  (0) 2023.01.06
    dart - mixin  (0) 2023.01.04

    댓글

Designed by Tistory.