이터레이터와 반복 가능한 객체
- 반복 가능한 객체(Iterable) : 하나씩 차례대로 값을 꺼내올 수 있는 객체
리스트, 튜플, 문자열, 딕셔너리 등은 모두 반복 가능한 객체
for 루프를 통해 반복, 내부적으로는 __iter__() 메서드를 통해 이터레이터 반환
numbers = [1, 2, 3, 4, 5]
for num in numbers:
print(num)
- 이터레이터(Iterator) : 반복 가능한 객체의 요소를 하나씩 꺼내오는 객체
numbers = [1, 2, 3, 4, 5]
iterator = iter(numbers) # 리스트로부터 이터레이터 생성
next(iterator) # 1 / 이터레이터의 각 요소를 하나씩 꺼내기
next(iterator) # 2
next(iterator) # 3
next(iterator) # 4
next(iterator) # 5
- 이터레이터의 동작 원리
- __iter__() : 이터레이터 객체 자신을 반환하는 메서드
- __next__() : 이터레이터 다음 요소를 반환하는 메서드
더 이상 반환할 요소가 없을 경우 StopIteration 예외를 발생시킴
- 이터레이터 구현 예시
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
# 이터레이터 사용
my_iter = MyIterator([1, 2, 3])
for a in my_iter: # for 루프 사용 가능
print(a)
# 1
# 2
# 3
제너레이터와 yield
- 제너레이터(Generator) : 이터레이터를 생성해주는 함수
yield를 사용해 값을 하나씩 반환 / 함수의 실행 상태 유지 / 다음 호출 시 그 상태에서 실행 재개
def generate_5():
yield 1
yield 2
yield 3
yield 4
yield 5
gen = generate_5()
next(gen) # 1
next(gen) # 2
next(gen) # 3
next(gen) # 4
next(gen) # 5
- 제네레이터의 장점
1. 메모리 효율성 : 필요할 때만 값을 생성해 메모리 사용률 감소
2. 계산 지연 : 결과를 즉시 계산하지 않고, 필요할 때 계산을 지연시킴
- 리스트 컴프리헨션 : 직관적으로 리스트를 생성하는 방법
test_list = [x * x for x in range(5)]
test_list # [0, 1, 4, 9, 16]
- 제네레이터 표현식 : 리스트 컴프리헨션과 비슷하지만, []대신 ()를 사용해 제너레이터 생성
test_list = (x * x for x in range(5))
for num in test_list:
print(num)
# 0
# 1
# 4
# 9
# 16
데코레이터와 with 구문(컨텍스트 매니저)
- 데코레이터(Decorator) : 함수나 메서드를 변경하지 않고, 꾸며주어 기능을 쉽게 추가함
- 데코레이터의 기본 구조
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
# 추가할 기능
print("추가 기능 실행 전")
result = original_function(*args, **kwargs)
print("추가 기능 실행 후")
return result
return wrapper_function
- 데코레이터 적용 예시
def display():
print("원래 함수 실행")
display()
# 원래 함수 실행
@decorator_function
def display():
print("원래 함수 실행")
display()
# 추가 기능 실행 전
# 원래 함수 실행
# 추가 기능 실행 후
display() 함수가 @decorator_function 데코레이터로 감싸져, 함수 실행 전후에 추가 기능이 실행됨
데코레이터는 시간을 측정하거나, 로그를 남길 때 유용하게 사용 가능
- 데코레이터 체이닝 : 여러 데코레이터를 하나의 함수에 적용
데코레이터는 안쪽(원래 함수에 가까운 순서)에서부터 밖으로 차례대로 적용
@decorator1
@decorator2 # decorator2 가 먼저 적용되고, decorator1 이 적용됨
def my_function():
pass
- with 구문(컨텍스트 매니저) : 특정 자원을 사용하는 경우, 자원을 얻고 사용한 뒤 자동으로 정리해주는 메커니즘
ex) 파일이나 데이터베이스를 열고 닫는 경우, with 구문을 사용해 코드의 시작과 끝에서 자동으로 설정 및 정리 작업 수행
with open("test.txt", "w") as f:
f.write("test") # test를 입력하고 자동으로 close