TIL/Python

241122 인공지능을 위한 파이썬 - 4주차_3

beady 2024. 11. 22. 17:09

이터레이터와 반복 가능한 객체

 

- 반복 가능한 객체(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