betterway13(이터레이터, 제너레이터 정의)

김승환·2021년 7월 11일

코딩의 기술

목록 보기
4/36

13 슬라이싱보다는 나머지를 모두 잡아내는 언패킹을 사용하라
기존의 한계점은 언패킹할 시퀀스의 길이를 미리 알고 있어야 한다는 것



# 언패킹을 할 때 시퀀스를 미리 알아야 한다는 문제의 예시

car_ages = [0, 9, 4, 8, 7, 20, 19, 1, 6, 15]
car_ages_descending = sorted(car_ages, reverse=True) #true일 경우 내림차순, flase일 경우 오름차순
print(car_ages_descending)
# 오류가 나는 부분. 오류를 보고 싶으면 커멘트를 해제할것
#oldest, second_oldest = car_ages_descending

[20, 19, 15, 9, 8, 7, 6, 4, 1, 0]

ValueError Traceback (most recent call last)
in
5 print(car_ages_descending)
6 # 오류가 나는 부분. 오류를 보고 싶으면 커멘트를 해제할것
----> 7 oldest, second_oldest = car_ages_descending

ValueError: too many values to unpack (expected 2)

이 경우 인덱스와 슬라이싱을 자주 사용한다.
여기서 문제점은 시각적으로 잡음이 많으며, 시퀀스 원소의 수를 실수하기 쉽다.

# 슬라이싱을 이용한 언패킹을 사용한 예시
oldest = car_ages_descending[0]
second_oldest = car_ages_descending[1]
others = car_ages_descending[2:]
print(oldest, second_oldest, others)

20 19 [15, 9, 8, 7, 6, 4, 1, 0]

개선 방법으로는 *(별표식)를 사용한다.

언패킹 패턴의 다른 부분에 들어가지 못하는 모든 값을 별이 붙은 부분에 담을 수 있다.
서로 다른 계층으로 이루어진다면 를 여러번 사용가능하다.(추천은 하지 않는 방식)
식에 더 이상 시퀀스가 없다면 빈 리스트 출력

  oldest, second_oldest, *others = car_ages_descending
print(oldest, second_oldest, others)
20 19 [15, 9, 8, 7, 6, 4, 1, 0]
# 다른 부분에도 * 사용 가능
oldest, *others, youngest = car_ages_descending
print(oldest, youngest, others)

*others, second_youngest, youngest = car_ages_descending
print(youngest, second_youngest, others)

20 0 [19, 15, 9, 8, 7, 6, 4, 1]
0 1 [20, 19, 15, 9, 8, 7, 6, 4]

  # *식만을 사용한 경우
*others = car_ages_descending

# *식을 두번 사용한 경우
first, *middle, *second_middle, last = [1, 2, 3, 4]
# 서로 다른 계층에 *를 여러번 사용한 예시
car_inventory = {
    '시내': ('그랜저', '아반테', '티코'),
    '공항': ('제네시스 쿠페', '소나타', 'K5', '악센트'),
}

((loc1, (best1, *rest1)),
 (loc2, (best2, *rest2))) = car_inventory.items()
print(f'{loc1} 최고는 {best1}, 나머지는 {len(rest1)} 종')
print(f'{loc2} 최고는 {best2}, 나머지는 {len(rest2)} 종')

시내 최고는 그랜저, 나머지는 2 종
공항 최고는 제네시스 쿠페, 나머지는 3 종

# *식에 더 이상 데이터가 없어서 빈 리스트를 출력하는 예시
short_list = [1, 2]
first, second, *rest = short_list
print(first, second, rest)

1 2 []

언패킹 구문을 이용해서 이터레이터를 가져올 수 있다.(추천은 x)

it = iter(range(1, 3))
first, second = it
print(f'{first} & {second}')

1 & 2

*식을 추가하면 언패킹할 이터레이터의 값을 깔끔하게 가지고 올 수 있다.

  # 기존 제너레이터를 이용하여 인덱스와 슬라이스를 사용하여 처리( 시각적 잡음이 많음.)
def generate_csv():
    yield ('날짜', '제조사' , '모델', '연식', '가격')
    for i in range(100):
        yield ('2019-03-25', '현대', '소나타', '2010', '2400만원')
        yield ('2019-03-26', '기아', '프라이드', '2008', '1400만원')

all_csv_rows = list(generate_csv())
header = all_csv_rows[0] #첫번째줄을 column name으로 설정
rows = all_csv_rows[1:] # 1행부터 값
print('CSV 헤더:', header)
print('행 수: ', len(rows))

CSV 헤더: ('날짜', '제조사', '모델', '연식', '가격')
행 수: 200

  # *식을 이용하여 정리하면 더 깔끔
it = generate_csv()
header, *rows = it
print('CSV 헤더:', header)
print('행 수: ', len(rows))
CSV 헤더: ('날짜', '제조사', '모델', '연식', '가격')

행 수: 200
이터레이터 : 이미 for문이나 list를 통해 주어진 객체로 부터 iter 메소드를 이용하여 각 요소를 하나하나 꺼내 처리할 수 있도록 함.

  # ex
s = "abc"
it = iter(s)
print(it)
print(next(it))
print(next(it))
print(next(it))

<str_iterator object at 0x000002268B2E1280>
a
b
c

제너레이터 : 함수 안에 이터레이터를 만드는 강력한 도구

  • yield 함수를 이용
  # 제너레이터 생성
def reverse(data):
    for index in range(len(data)-1,-1,-1):
        yield data[index]
        
for char in reverse("golf"):
    print(char)

f
l
o
g

profile
인공지능 파이팅!

0개의 댓글