[개발] 파이썬

6.1. 파이썬 데코레이터와 제너레이터

브랜든정 2024. 12. 27. 10:45
반응형

파이썬은 함수와 클래스를 효율적으로 사용하기 위해 다양한 기법을 제공합니다. 이 중에서 데코레이터와 제너레이터는 특히 유용한 도구들입니다. 이 글에서는 파이썬 데코레이터와 제너레이터를 사용하여 함수를 효율적으로 사용하는 방법을 설명하겠습니다.

1. 파이썬 데코레이터의 개념

1.1 데코레이터의 정의

데코레이터는 함수를 다른 함수로 감싸서 함수의 동작을 변경하거나 확장하는 기법입니다. 데코레이터를 사용하면 함수의 실행 전후에 특정 동작을 수행할 수 있습니다. 데코레이터는 함수를 감싸는 역할을 하기 때문에 함수의 원래 동작을 유지하면서도 추가적인 기능을 제공할 수 있습니다.

1.2 데코레이터의 예시

데코레이터를 사용하는 가장 간단한 예시는 함수의 실행 시간을 측정하는 것입니다. 다음과 같이 데코레이터를 정의하고 사용할 수 있습니다:

import time

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} executed in {end_time - start_time} seconds")
        return result
    return wrapper

@timer_decorator
def example_function():
    time.sleep(1)  # Simulate some work

example_function()

이 예시에서 timer_decoratorexample_function을 감싸서 실행 시간을 측정합니다. @timer_decorator를 사용하여 example_function을 데코레이팅하면, example_function의 실행 시간이 자동으로 측정됩니다.

1.3 데코레이터의 활용

데코레이터는 다양한 상황에서 유용합니다. 예를 들어, 로깅을 위한 데코레이터를 만들면 로그를 자동으로 기록할 수 있습니다. 다음과 같이 로깅 데코레이터를 정의할 수 있습니다:

import logging

logging.basicConfig(level=logging.INFO)

def logging_decorator(func):
    def wrapper(*args, **kwargs):
        logging.info(f"Calling function {func.__name__} with arguments {args} and keyword arguments {kwargs}")
        result = func(*args, **kwargs)
        logging.info(f"Function {func.__name__} returned {result}")
        return result
    return wrapper

@logging_decorator
def example_function(name, age):
    return f"Hello, {name} You are {age} years old."

print(example_function("Alice", 30))

이 예시에서 logging_decoratorexample_function을 감싸서 로그를 기록합니다. @logging_decorator를 사용하여 example_function을 데코레이팅하면, example_function의 호출과 반환 값이 자동으로 로그에 기록됩니다.

2. 파이썬 제너레이터의 개념

2.1 제너레이터의 정의

제너레이터는 함수를 정의할 때 yield 키워드를 사용하여 함수가 값을 반환할 때마다 중간에 멈추고 다음에 값을 반환할 때 다시 시작할 수 있는 함수입니다. 제너레이터는 함수를 호출할 때마다 값을 한 번에 하나씩 반환하므로, 메모리 사용량을 줄일 수 있습니다.

2.2 제너레이터의 예시

제너레이터를 사용하는 가장 간단한 예시는 숫자 시퀀스를 생성하는 것입니다. 다음과 같이 제너레이터를 정의할 수 있습니다:

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

sequence = infinite_sequence()
for _ in range(10):
    print(next(sequence))

이 예시에서 infinite_sequence는 숫자 시퀀스를 생성하는 제너레이터입니다. next(sequence)를 사용하여 시퀀스의 다음 값을 가져올 수 있습니다.

2.3 제너레이터의 활용

제너레이터는 다양한 상황에서 유용합니다. 예를 들어, 큰 데이터 집합을 처리할 때 제너레이터를 사용하면 메모리 사용량을 줄일 수 있습니다. 다음과 같이 제너레이터를 사용하여 큰 데이터 집합을 처리할 수 있습니다:

def read_large_file(file_path):
    with open(file_path, 'r') as file:
        for line in file:
            yield line.strip()

for line in read_large_file('large_data.txt'):
    print(line)

이 예시에서 read_large_file는 큰 파일을 읽는 제너레이터입니다. for 루프를 사용하여 파일의 각 줄을 처리할 수 있습니다.

3. 데코레이터와 제너레이터를 함께 사용하는 방법

데코레이터와 제너레이터를 함께 사용하면 함수의 동작을 더 효율적으로 관리할 수 있습니다. 예를 들어, 데코레이터를 사용하여 제너레이터의 동작을 기록할 수 있습니다:

import time
import logging

logging.basicConfig(level=logging.INFO)

def logging_decorator(func):
    def wrapper(*args, **kwargs):
        logging.info(f"Calling function {func.__name__} with arguments {args} and keyword arguments {kwargs}")
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        logging.info(f"Function {func.__name__} returned {result} in {end_time - start_time} seconds")
        return result
    return wrapper

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

sequence = infinite_sequence()
for _ in range(10):
    print(next(sequence))

# 데코레이터를 사용하여 제너레이터의 동작을 기록
@logging_decorator
def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

sequence = infinite_sequence()
for _ in range(10):
    print(next(sequence))

이 예시에서 logging_decorator를 사용하여 infinite_sequence의 동작을 기록합니다. @logging_decorator를 사용하여 infinite_sequence을 데코레이팅하면, infinite_sequence의 호출과 반환 값이 자동으로 로그에 기록됩니다.

파이썬 데코레이터와 제너레이터는 함수를 효율적으로 사용하는 데 매우 유용한 도구들입니다. 데코레이터를 사용하면 함수의 동작을 변경하거나 확장할 수 있으며, 제너레이터를 사용하면 함수가 값을 한 번에 하나씩 반환할 수 있습니다. 데코레이터와 제너레이터를 함께 사용하면 함수의 동작을 더 효율적으로 관리할 수 있습니다. 이러한 기법을 사용하여 함수를 더 효율적으로 사용할 수 있습니다.

반응형