python 이터러블, 이터레이터, 제너레이터

차지예·2025년 5월 16일

생성AI

목록 보기
4/56
post-thumbnail

🟡이터러블(iterable)

파이썬에서 반복문을 사용할 수 있는 객체를 이터러블 하다고 한다.

이터러블 한지 알수 있는 방법은 iter()함수를 사용하는 것이다.

a = 1
print(iter(a))

#TypeError: 'int' object is not iterable <- 이터러블하지 않다는 것이다.
a =[1,2,3,4]
print(iter(a))

<list_iterator object at 0x7da0c1b5ab30> <- 이터러블 하다는 것이다.

여기서 알 수 있는 사실은 정수 타입의 객체는 반복문을 사용할 수 없는 것이다.

a = 1
for i in a:
  print(i)  # <- 이것 또한 이터러블하지 않다는 타입 오류가 나온다.

반면 리스트, 튜플, 딕셔너리, 문자열는 반복문을 사용 가능하다입니다.

lst = [1, 2, 3]       # 리스트
s = "hello"           # 문자열
t = (10, 20, 30)      # 튜플
d = {"a": 1, "b": 2}  # 딕셔너리

for char in lst:
    print(char)  


for char in s:
    print(char)  


for char in t:
    print(char)  


for char in d:
    print(char)           # 전부다 반복문이 가능하다

🟡이터러블(iterable) 객체와 이터레이터 객체

어떤 객체가 __iter__ 메소드를 포함하고 있는 객체를 이터러블 객체라고 한다.

iter이라는 내장함수를 호출하면 내부적으로 해당 객체의 __iter__메소드를 호출하게 됩니다.

__iter__메소드는 이터레이터 객체를 반환해주는데 여기서 이터레이터 객체는 __next__ 메소드를 반드시 구현하고 있어야 한다.


class MyIterator:
  def __next__(self):
    return 1

class MyIterable:
  def __iter__(self):
    obj = MyIterator()
    return obj

m = MyIterable()     # 이터러블 객체 생성
r = iter(m)          # 이터레이터 생성
print(next(r))       # 1
print(next(r))       # 1
print(next(r))       # 1

✅ 객체 분석
🔹 MyIterator 클래스

class MyIterator:
  def __next__(self):
    return 1
  • __next__() 메서드만 정의되어 있음.
  • __iter__()는 없지만, 이터레이터로 사용 가능 (파이썬은 __next__()만 있어도 내부적으로 이터레이터로 간주할 수 있음).
  • __next__() 메서드에서 언제나 1을 반환하기 때문에, next()를 계속 호출해도 끝이 없습니다. 즉, 무한 루프처럼 작동하게 됩니다.

👉 이터레이터 객체 역할


🔹 MyIterable 클래스

class MyIterable:
  def __iter__(self):
    obj = MyIterator()
    return obj
  • __iter__() 메서드가 있음 → 이 클래스는 이터러블(Iterable)
  • iter(m)을 호출하면 MyIterator 객체를 리턴함

👉 이터러블 객체 역할


❓그럼 이터레이터에도 __iter__()가 필요할까?

사실 이터레이터 객체도 __iter__() 메서드를 가져야 합니다.
왜냐하면 파이썬은 내부적으로 아래와 같은 조건을 만족해야 정상적인 이터레이터로 간주합니다:

이터레이터란?
__next__()__iter__()를 모두 가진 객체이고,__iter__()는 자기 자신을 반환해야 함.


✅ StopIteration 예외

class MyIterator:
    def __init__(self):
        self.data = [1, 2, 3]
        self.index = 0

    def __iter__(self):
      return self    

    def __next__(self):
        if self.index < len(self.data):
            value = self.data[self.index]
            self.index += 1
            return value
        else:
            raise StopIteration 

next()를 3번 호출하면 1, 2, 3 출력하고
(4번 출력시)그 다음 호출 시 StopIteration 예외가 발생합니다.
🔹 실제 for 문은 StopIteration 예외를 감지해서 자동으로 멈춥니다.


그림과 같이 보통 iterator객체를 얻기 위해 iter내장 함수에 iterable 객체를 입력해서 iterator객체를 출력받고 다시 iterator객체를 iter내장 함수에 넣어도 iterator객체를 리턴해 준다.

map(), filter()

깃허브에 코드 정리되어있어서 생략

https://github.com/pinggu95/deep_dive_AI/blob/main/4일차_python_모듈.ipynb


🟡제너레이터(generator)

일반 함수와 비슷하지만, 값을 한 번에 하나씩 생성하면서 순차적으로 반환하고, 필요한 시점에만 계산을 수행해 메모리 효율이 높다.

제너레이터는 제너레이터 함수를 통해 만들수 있다.

제너레이터의 특징

  1. yield 키워드 사용
  • 일반 함수는 return을 사용하지만, 제너레이터는 yield를 사용합니다.
  • yield는 값을 "반환하고 일시 중지"합니다. 다음 호출 시 그 다음 줄부터 실행이 이어집니다.
  1. 게으른 평가(lazy evaluation)
  • 한 번에 모든 값을 메모리에 저장하지 않고, 필요할 때마다 하나씩 계산합니다.

위 그림에서 함수의 상태가 상태 유지 된다는것을 알수 있다.


def num_gen():
  for i in range(3):
    yield  i

g= num_gen()

print(type(g))     # <class 'generator'>
print(next(g))     # 0  
print(next(g))     # 1 
print(next(g))     # 2

제너레이터는 큰 규모의 확장성이 있는 프로그램을 개발하기 위해 사용한다고 말할수 있다.

0개의 댓글