Python to AI

Decorator, Context Manager

최 수빈 2024. 11. 14. 17:38

 

 데코레이터(Decorator)

 

함수나 메서드를 변경하지 않고, 추가적인 기능을 쉽게 추가할 수 있는 방법

함수나 다른 함수를 감싸서 원래 함수에 새로운 기능을 덧붙인다.

 

데코레이터를 적용하려는 함수 위에 '@데코레이터이름'을 붙여 사용

 

 

*장점

 

코드 재사용성 - 동일한 기능을 여러 함수에 적용할 수 있음

코드 가독성 향상 - 코드 구조가 깔끔해지고, 함수의 로직에만 집중할 수 있음

중복 코드 제거 - 반복되는 코드 패턴을 제거하고, 간결하게 유지할 수 있음

 

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
    	#추가할 기능
        print("추가할 기능 실행 전")
        result = original_function(*args, **kwargs)
        print("추가 기능 실행 후")
        return result
    return wrapper_function

 

@decorator_function
def display():
    print("원래 함수 실행")
    
#함수 호출
display()

#display함수는 @decorator_function 데코레이터로 감싸져서, 함수 실행 전후에 추가 기능이 실행됨


#추가할 기능 실행 전
#원래 함수 실행
#추가 기능 실행 후
#데코레이터 예시

def log_decorator(func):
	def wrapper(*args,**kwargs):
    	print(f"실행 전: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"실행 후": {func.__name__}")
        result result
     return wrapper
      
@log_decorator
def say_hello(name):
	print(f"안녕하세요, {name}님!")
    
#함수 호출
say_hello("Alice")

#실행 전: say_hello
#안녕하세요. Alice님!
#실행 후: say_hello

 

 데코레이터 체이닝 구조

 

여러 데코레이터를 하나의 함수에 적용할 수 있으며, 이 경우 데코레이터는 안쪽에서 밖으로 차례대로 적용

 

@decorator1
@decorator2
def my_function():
    pass

#decorator2가 먼저 적용, decorator1이 추가로 적용

 

 

 

 

with구문 (컨텍스트 매니저 - Context Manager)

 

리소스를 획득하고 사용한 뒤, 자동으로 정리해주는 메커니즘

코드의 시작과 끝에서 자동으로 설정 및 정리 작업 수행

 

with 컨텍스트매니저 as 변수:

    #작업 수행

 

 

 

컨텍스트 매니저의 작동 원리

 

__enter__(), __exit__()사용

 

__enter__() : with블록에 진입할 때 호출 됨, 필요한 리소스를 준비하거나, 설정 작업을 수행

__exit__() : with블록이 끝날 때 호출 됨, 리소스를 정리하고 예외 처리 수행

 

*장점

자동 리소스 관리 - 파일, 네트워크 연결, 데이터베이스 연결 등 리소스를 자동으로 정리할 수 있음

에러 처리 간소화 - with 블록 내부에서 예외가 발생해도, __exit__()메서드가 호출되어 안전하게 리소스 정리 가능

코드 가독성 향상 - 리소스 관리 명확하고 일관되게 처리할 수 있어 코드의 가독성 향상

 

*컨텍스트 매니저 활용 사례

파일 처리 - 파일을 열고 닫는 작업 안전하게 처리

데이터베이스 연결 - 데이터베이스 연결을 열고, 작업 후 자동으로 연결 종료

락(lock) 관리 - 멀티스레딩 환경에서 락을 획득하고, 작업이 끝나면 자동으로 락을 해제

 

 

 

#with구문을 사용한 파일 처리 예시

with open("example.txt","r") as file:
    content = file.read()
    print(content)
#컨텍스트 매니저 구현 예시

class MyContextManager:
    def __enter__(self):
        print("리소스를 획득합니다.")
        return self
    def __exit__(self, exc_type, exc_value, traceback):
        print("리소스를 정리합니다.")
        
#컨텍스트 매니저 사용
with MyContextManager():
    print("작업 수행 중...")
    
#with구문을 통해 __enter__()와 __exit__()메서드 자동 호출


#리소스를 획득합니다.
#작업 수행 중...
#리소스를 정리합니다.

 

exc_type : 컨텍스트 블록 안에서 예외가 발생했을 때 예외의 타입

exc_value: 발생한 예외의 실제 값 (예 : ZeroDivisionError("division by zero")와 같은 예외가 발생하면 "division by zero"라는 문자열이 exc_value로 전달됨)

traceback: 예외가 발생한 트레이스백 객체 - 예외가 발생한 위치, 호출 스택 등 디버깅에 유용한 정보를 담고 있음

 

=> 이 매개변수들은 with블록 안에서 예외가 발생했을 때에만 __exit__메서드로 전달되고, 예외가 없으면 모두 None이 됨