이터레이터 (iterator)

이해하기 쉽고, 장황하지 않은 자료를 기반으로 강의를 진행합니다.
잔재미코딩 소식 공유
좀더 제약없이, IT 컨텐츠를 공유하고자, 자체 온라인 사이트와, 다음 두 채널도 오픈하였습니다
응원해주시면, 곧 좋은 컨텐츠를 만들어서 공유하겠습니다
●  잔재미코딩 뉴스레터 오픈 [구독해보기]
●  잔재미코딩 유투브 오픈 [구독해보기]

19. 이터레이터 (iterator)

  • 몇몇 특수한 데이터 집합은 내부의 각 데이터로 분리해서 처리할 수 있음
  • 예:
    • list, set, dictionary 등의 컬렉션(collection)
    • 문자열: 문자열을 이루는 각 문자 Sequence
  • 이와 같은 컬렉션(collection), Sequence등을 iterable 객체(iterable Object)라고 함
  • 간단히 for 구문으로 각 데이터를 탐색할 수 있는 데이터 집합
In [ ]:
# 예1: 리스트 컬렉션
for num in [1, 2, 3, 4, 5]:
    print(num)
In [ ]:
# 예2: 문자 Sequence
for char in "Dave Lee":
    print(char)

iterable 과 iterator

  • iterable 객체: itertator를 리턴할 수 있는 객체
    • 이터레이터를 리턴할 수 있는 객체
  • iterator
    • 순차적으로 다음 데이터를 리턴할 수 있는 객체
    • Iterator는 내장 함수 next 함수를 사용해서, 순환하는 다음 값을 반환함

내장 함수 iter()

  • iterator 객체를 생성할 수 있음
In [ ]:
my_list = [1, 2, 3, 4, 5]
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [ ]:
print(next(my_list))
In [ ]:
my_list_iterator = iter(my_list)
In [ ]:
print(next(my_list_iterator))

내장 함수 next()

  • Iterator의 다음 값, 즉 순환하는 값을 반환
In [ ]:
iterator_my_list = iter(my_list)
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [ ]:
next(iterator_my_list)
In [ ]:
next(iterator_my_list)
next(iterator_my_list)
next(iterator_my_list)
next(iterator_my_list)
In [ ]:
# 더이상 순회할 데이터가 없으면, StopIteration 발생
next(iterator_my_list)

for 구문과 iterator

  • for 구문 사용시, 파이썬은 매번 next 함수로 iterator의 다음 값을 읽어내는 것임
  • StopIteration 발생할 때까지 next 함수를 호출한다고 보면 됨

Custom 이터레이터 만들기

  • 직접 만들 수 있음
    • iterable 객체는 iter 메서드를 가지고 있는 클래스
    • iterator 객체는 next 메서드를 가지고 있는 클래스
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다

iterable 객체와 iterator 클래스 만들기

In [ ]:
class Counter:
    def __init__(self, stop):
        self.stop = stop    # 반복을 끝낼 숫자
 
    def __iter__(self):                      # <--- iterable 객체는 __iter__ 메서드가 존재함
        return Counter_Iterator(self.stop)   # <--- Counter 의 iterator 객체를 리턴해줌

class Counter_Iterator:
    def __init__(self, stop):
        self.current = 0    # 현재 상태를 확인하기 위한 속성
        self.stop = stop    

    def __next__(self):                 # <--- iterator는 __next__ 메서드가 존재함
        if self.current < self.stop:    # 현재 상태가 stop보다 적을 때는 현재 상태값을 리턴해주고, 1씩 상태값을 증가시킴
            return_value = self.current            
            self.current += 1           
            return return_value         
        else:                           # 현재 상태가 stop과 동일 또는 클 때는 StopIteration 이벤트를 발생시킴 
            raise StopIteration         # 예외 발생
In [ ]:
counter_iterator = iter(Counter(5))
In [ ]:
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
In [ ]:
for num in Counter(3):
    print (num)
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다

iterable 객체이자 iterator로 한번에 클래스 만들기

In [ ]:
class Counter:
    def __init__(self, stop):
        self.current = 0    # 현재 상태를 확인하기 위한 속성
        self.stop = stop    # 반복을 끝낼 숫자
 
    def __iter__(self):                      # <--- iterable 객체는 __iter__ 메서드가 존재함
        return self   # <--- Counter 의 iterator 객체를 리턴해줌

    def __next__(self):                 # <--- iterator는 __next__ 메서드가 존재함
        if self.current < self.stop:    # 현재 상태가 stop보다 적을 때는 현재 상태값을 리턴해주고, 1씩 상태값을 증가시킴
            return_value = self.current            
            self.current += 1           
            return return_value         
        else:                           # 현재 상태가 stop과 동일 또는 클 때는 StopIteration 이벤트를 발생시킴 
            raise StopIteration         # 예외 발생
In [ ]:
counter_iterator = iter(Counter(5))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
In [ ]:
# iterable 객체이자 iterator임
print (next(Counter(2)))
In [ ]:
for num in Counter(3):
    print (num)
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [ ]:
def iter(object):
    return object.__iter__()

def next(object):
    return object.__next__()

for num in range(10):
    
In [ ]:
class Counter:
    def __init__(self, stop):
        self.stop = stop    # 반복을 끝낼 숫자
 
    def __iter__(self):                      # <--- iterable 객체는 __iter__ 메서드가 존재함
        return Counter_Iterator(self.stop)   # <--- Counter 의 iterator 객체를 리턴해줌

class Counter_Iterator:
    def __init__(self, stop):
        self.current = stop    # 현재 상태를 확인하기 위한 속성
        self.stop = stop    

    def __next__(self):                 # <--- iterator는 __next__ 메서드가 존재함
        if self.current > 0:    # 현재 상태가 stop보다 적을 때는 현재 상태값을 리턴해주고, 1씩 상태값을 증가시킴
            return_value = self.current            
            self.current -= 1           
            return return_value         
        else:                           # 현재 상태가 stop과 동일 또는 클 때는 StopIteration 이벤트를 발생시킴 
            raise StopIteration         # 예외 발생
In [ ]:
counter_iterator = iter(Counter(5))
print(next(counter_iterator))
print(next(counter_iterator))
print(next(counter_iterator))
print(next(counter_iterator))
print(next(counter_iterator))
초간단 연습1
- 위 Counter 클래스는 인자로 넣어지는 수까지를 0부터 순차적으로 1씩 증가된 값을 리턴해주는 클래스입니다.
- 이번에는 인자로 넣어지는 수부터 시작해서 0까지 순차적으로 1씩 감소된 값을 리턴해주는 클래스를 만들어보세요
In [ ]:
class Counter:
    def __init__(self, stop):
        self.stop = stop    # 반복을 끝낼 숫자
 
    def __iter__(self):                      # <--- iterable 객체는 __iter__ 메서드가 존재함
        return Counter_Iterator(self.stop)   # <--- Counter 의 iterator 객체를 리턴해줌

class Counter_Iterator:
    def __init__(self, stop):
        self.current = stop    # 현재 상태를 확인하기 위한 속성

    def __next__(self):                 # <--- iterator는 __next__ 메서드가 존재함
        if self.current > 0:    # 현재 상태가 stop보다 적을 때는 현재 상태값을 리턴해주고, 1씩 상태값을 증가시킴
            return_value = self.current            
            self.current -= 1           
            return return_value         
        else:                           # 현재 상태가 stop과 동일 또는 클 때는 StopIteration 이벤트를 발생시킴 
            raise StopIteration         # 예외 발생

counter_iterator = iter(Counter(5))
print (next(counter_iterator))
print (next(counter_iterator))
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
협업 과제1(남에게 설명하면, 자신이 배운답니다.!)
- 특정 수와 배수를 입력받아 특정 수의 배수를 특정 수까지 리턴하는 이터레이터 만들기
예: 20, 2 를 입력받으면 0, 2, 4, ~~~ 20까지 리턴
In [ ]:
class Counter:
    def __init__(self, stop, multiple):
        self.current = 0    # 현재 상태를 확인하기 위한 속성
        self.stop = stop    # 반복을 끝낼 숫자
        self.multiple = multiple
 
    def __iter__(self):                      # <--- iterable 객체는 __iter__ 메서드가 존재함
        return self   # <--- Counter 의 iterator 객체를 리턴해줌

    def __next__(self):                 # <--- iterator는 __next__ 메서드가 존재함
        if self.current < self.stop:    # 현재 상태가 stop보다 적을 때는 현재 상태값을 리턴해주고, 1씩 상태값을 증가시킴
            return_value = self.current            
            self.current = self.current + self.multiple           
            return return_value         
        else:                           # 현재 상태가 stop과 동일 또는 클 때는 StopIteration 이벤트를 발생시킴 
            raise StopIteration         # 예외 발생

counter_iterator = iter(Counter(20, 2))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))
print (next(counter_iterator))

협업 과제2(남에게 설명하면, 자신이 배운답니다.!)
다음 dataset은 이름을 가지고 있습니다. (타이타닉호 승선자 명단)
스트링에서 Mr. Miss, Mrs. 정보를 추출해서 각각 (Male), (Female) 출력해주는 데코레이터를 작성하세요
해당 데코레이터를 활용해서 이름 정보 리스트 변수를 넣어, 이름을 추력하는 함수를 작성해보세요
dataset과 이름에서 Mr. Miss. Mrs. 정보를 추출하는 코드는 다음 코드를 참고하세요

In [ ]:
dataset = ['Braund, Mr. Owen Harris',
'Cumings, Mrs. John Bradley (Florence Briggs Thayer)',
'Heikkinen, Miss. Laina',
'Futrelle, Mrs. Jacques Heath (Lily May Peel)',
'Allen, Mr. William Henry',
'Moran, Mr. James',
'McCarthy, Mr. Timothy J',
'Palsson, Master. Gosta Leonard',
'Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)',
'Nasser, Mrs. Nicholas (Adele Achem)',
'Sandstrom, Miss. Marguerite Rut',
'Bonnell, Miss. Elizabeth',
'Saundercock, Mr. William Henry',
'Andersson, Mr. Anders Johan',
'Vestrom, Miss. Hulda Amanda Adolfina',
'Hewlett, Mrs. (Mary D Kingcome) ',
'Rice, Master. Eugene',
'Williams, Mr. Charles Eugene',
'Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele)',
'Masselmani, Mrs. Fatima',
'Fynney, Mr. Joseph J',
'Beesley, Mr. Lawrence',
'McGowan, Miss. Anna "Annie"',
'Sloper, Mr. William Thompson',
'Palsson, Miss. Torborg Danira',
'Asplund, Mrs. Carl Oscar (Selma Augusta Emilia Johansson)',
'Emir, Mr. Farred Chehab',
'Fortune, Mr. Charles Alexander',
'Dwyer, Miss. Ellen "Nellie"',
'Todoroff, Mr. Lalio']
In [ ]:
import re
p = re.compile('([A-Za-z]+)\.')
for name in dataset:
    matched = p.search(name)
    print(matched.group())
본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다

이름에서 앞에 이름만 빼고 싶은 분들이 있었음

In [ ]:
import re
for name in dataset:
    names = name.split(' ')
    print (names[0])
참고
다음 코드는 openpyxl 라이브러리로 엑셀파일에서 이름 데이터를 읽어내는 코드입니다.
실제로 대량의 데이터를 읽어내는 코드입니다.
간단한 문제: F 로 시작하는 이름만 2번째 열에 F 로 표시하기
In [ ]:
import openpyxl
 
# 엑셀파일 열기
wb = openpyxl.load_workbook('data/name.xlsx')
 
# 현재 Active Sheet 얻기
ws = wb.active
# ws = wb.get_sheet_by_name("Sheet1")

for r in ws.rows:
    name = r[0].value
    if name[0] == 'F':
        ws.cell(row=r[0].row, column=2).value = 'F'
    # ws.cell(row=row_index, column=5).value = sum
 
    print(name)
 
# 엑셀 파일 저장
wb.save("score2.xlsx")
wb.close()

협업과제2를 실제 엑셀파일까지 연계해서 풀어보기

본 자료와 같이 IT 기술을 잘 정리하여, 온라인 강의로 제공하고 있습니다
체계적으로 전문가 레벨까지 익힐 수 있도록 온라인 강의 로드맵을 제공합니다
In [ ]:
import openpyxl
import re
# 엑셀파일 열기
wb = openpyxl.load_workbook('data/name.xlsx')
 
# 현재 Active Sheet 얻기
ws = wb.active
# ws = wb.get_sheet_by_name("Sheet1")

for r in ws.rows:
    name = r[0].value
    p = re.compile('([A-Za-z]+)\.')
    if p.search(name):
        matched = p.search(name)
        if matched.group() == 'Mr.' or matched.group() == 'Master.':
            ws.cell(row=r[0].row, column=2).value = '(Male)'
        elif matched.group() == 'Mrs.' or matched.group() == 'Miss.' or matched.group() == 'Ms.':
            ws.cell(row=r[0].row, column=2).value = '(Female)'
        else:
            ws.cell(row=r[0].row, column=2).value = '(Unknown)'
 
# 엑셀 파일 저장
wb.save("score2.xlsx")
wb.close()