파이썬 고급 문법: 데코레이터와 제너레이터
데코레이터와 제너레이터의 개념과 활용 방법
파이썬은 효율적이고 가독성 높은 코드를 작성할 수 있는 고급 기능을 제공합니다. 데코레이터(Decorator)와 제너레이터(Generator)는 이러한 기능 중 두 가지로, 각각 함수 확장과 효율적인 데이터 처리를 가능하게 합니다. 이번 글에서는 이 두 가지 개념과 활용 방법을 살펴보겠습니다.
1. 데코레이터란?
데코레이터는 함수나 메서드의 동작을 확장하거나 수정할 수 있는 함수입니다. 다른 함수를 감싸서 새로운 기능을 추가하는 데 사용됩니다.
2. 데코레이터의 기본 구조
기본 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def decorator(func):
def wrapper(*args, **kwargs):
print("기능 추가 전")
result = func(*args, **kwargs)
print("기능 추가 후")
return result
return wrapper
@decorator
def say_hello():
print("Hello, World!")
say_hello()
# 출력:
# 기능 추가 전
# Hello, World!
# 기능 추가 후
3. 데코레이터 활용
1) 실행 시간 측정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"실행 시간: {end_time - start_time:.4f}초")
return result
return wrapper
@timer
def long_task():
time.sleep(2)
print("작업 완료!")
long_task()
# 출력:
# 작업 완료!
# 실행 시간: 2.0001초
2) 인증 시스템
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def require_auth(func):
def wrapper(user_authenticated, *args, **kwargs):
if not user_authenticated:
print("인증이 필요합니다!")
return
return func(*args, **kwargs)
return wrapper
@require_auth
def access_secure_area(user_authenticated):
print("보안 구역에 접근했습니다.")
access_secure_area(False) # 출력: 인증이 필요합니다!
access_secure_area(True) # 출력: 보안 구역에 접근했습니다.
3) 다중 데코레이터
- 여러 데코레이터를 동시에 사용할 수 있습니다. 위에서부터 아래로 실행됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def decorator_one(func):
def wrapper(*args, **kwargs):
print("Decorator One")
return func(*args, **kwargs)
return wrapper
def decorator_two(func):
def wrapper(*args, **kwargs):
print("Decorator Two")
return func(*args, **kwargs)
return wrapper
@decorator_one
@decorator_two
def greet():
print("Hello!")
greet()
# 출력:
# Decorator One
# Decorator Two
# Hello!
4. 제너레이터란?
제너레이터(Generator)는 이터레이터를 생성하는 함수로, 데이터를 한 번에 메모리에 올리지 않고 필요한 순간에 값을 생성합니다. yield
키워드를 사용하여 데이터를 반환합니다.
5. 제너레이터의 기본 구조
기본 구조
1
2
3
4
5
6
7
8
9
10
11
def generator_function():
yield 1
yield 2
yield 3
for value in generator_function():
print(value)
# 출력:
# 1
# 2
# 3
yield
는 값을 반환하면서 함수의 상태를 저장합니다.next()
를 호출하면 다음 값을 반환합니다.
예제
1
2
3
4
gen = generator_function()
print(next(gen)) # 출력: 1
print(next(gen)) # 출력: 2
print(next(gen)) # 출력: 3
6. 제너레이터의 활용
1) 대규모 데이터 처리
- 제너레이터는 메모리를 절약하며 데이터를 처리할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
for num in count_up_to(5):
print(num)
# 출력:
# 1
# 2
# 3
# 4
# 5
2) 무한 데이터 스트림
- 제너레이터를 사용하면 무한 데이터 스트림을 쉽게 처리할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
def infinite_sequence():
num = 0
while True:
yield num
num += 1
gen = infinite_sequence()
print(next(gen)) # 출력: 0
print(next(gen)) # 출력: 1
print(next(gen)) # 출력: 2
3) 제너레이터 표현식
- 리스트 컴프리헨션과 유사하지만, 메모리 효율이 높습니다.
1
2
3
4
5
6
7
8
9
gen = (x ** 2 for x in range(5))
for value in gen:
print(value)
# 출력:
# 0
# 1
# 4
# 9
# 16
7. 데코레이터와 제너레이터의 결합
데코레이터와 제너레이터를 함께 사용하면 더욱 강력한 기능을 구현할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def generator_decorator(func):
def wrapper(*args, **kwargs):
gen = func(*args, **kwargs)
for value in gen:
yield value ** 2
return wrapper
@generator_decorator
def numbers():
for i in range(5):
yield i
for value in numbers():
print(value)
# 출력:
# 0
# 1
# 4
# 9
# 16
정리
- 데코레이터: 함수의 동작을 확장하고 반복 코드를 줄이는 강력한 도구.
- 제너레이터: 데이터를 한 번에 메모리에 올리지 않고, 필요한 순간에 생성하는 효율적인 함수.
- 두 기능을 조합하여 강력하고 효율적인 프로그램을 작성할 수 있습니다.
다음 글 예고:
파이썬의 심화 주제로, “컨텍스트 매니저”를 배워보겠습니다!
This post is licensed under CC BY 4.0 by the author.