파이썬 코딩을 더 깔끔하게! #12

Dunno·2021년 7월 4일
0

Better Way 13. 슬라이싱보다는 나머지를 모두 잡아내는 언패킹을 사용하라

기존 언패킹의 문제점

기본 언패킹은 언패킹할 시퀀스의 길이를 알아야 한다는 단점이 있다.

car_ages = [0, 9, 4, 8, 7, 20, 19, 1, 6, 15]
car_ages_descending = sorted(car_ages, reverse=True)
oldest, second_oldest = car_ages_descending

>>>
Traceback...
ValueError: too many values to unpack (expected 2)

해결방법 1. 인덱스와 슬라이싱

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]
  • 시각적인 잡음이 많다.
  • 범위를 변경했는데 다른 줄에서 고치지 않으면 결과가 잘못되거나 예외가 발생할 수 있다.

해결방법 2. 별표식

  • 언패킹 패턴의 다른 부분에 들어가지 못하는 모든 값을 별이 붙은 부분에 다 담을 수 있다.
oldest, second_oldest, *others = car_ages_descending
print(oldest, second_oldest, others)

>>>
20 19 [15, 9, 8, 7, 6, 4, 1, 0]
  • 더 짧고 읽기 쉽고, 여러 줄 사이에 인덱스 경계 값이 어긋나서 오류가 발생할 여지도 없다.

별표식의 응용

# oldest와 youngest만 추출
oldest, *others, youngest = car_ages_descending
print(oldest, youngest, others)

# youngest, second_youngest만 추출
*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

>>>
Traceback ...
SyntaxError: started assignment target must be in a list or tuple
  • 한 언패킹 패턴에 별표 식을 두 개 이상 쓸 수 없다.
first, *middle, *second_middle, last = [1,2,3,4]

>>>
Traceback ...
SyntaxError: two starred expressions in assignment
  • 여러 계층으로 이뤄진 구조를 언패킹할 때는 서로 다른 부분에 포함되는 한, 별표 식을 여럿 사용해도 된다.
car_inventory = {
	'시내' : ('그랜저', '아반떼', '티코'),
	'공항' : ('제네시스 쿠페', '소나타', 'K5', '엑센트'),
}

((loc1, (best1, *rest1)),
 (loc2, (best2, *rest2))) = car_inventory.items()

print(f'{loc1} 최고는 {best1}, 나머지는 {len(rest1)} 종'}
print(f'{loc2} 최고는 {best2}, 나머지는 {len(rest1)} 종'}
  • 언패킹하는 시퀀스에 남는 원소가 없으면 별표 식 부분은 빈 리스트가 된다
short_list = [1, 2]
first, second, *rest = short_list
print(first, second, rest)

>>>
1 2 []
  • *를 추가하면 언패킹할 이터레이터의 값을 깔끔하게 가져올 수 있다.
def generate_csv():
	yield('날짜', '제조사', '모델', '연식', '가격')
  1. 제너레이터의 결과를 인덱스와 슬라이드를 사용해 출력

비추천

all_csv_rows = list(generate_csv())
header = all_csv_rows[0]
rows = all_csv_rows[1:]
print('CSV 헤더:', header)
  1. 제너레이터의 결과를 *식으로 언패킹해서 헤더와 나머지를 쉽게 나눠서 처리할 수 있다.

추천

it = generate_csv()
header, *rows = it
print('CSV 헤더', header)

주의점!!

* 식은 항상 리스트를 만들어 낸다 !!
만약 이터레이터를 *로 언패킹하면 컴퓨터 메모리를 모두 사용해버려서 프로그램이 다운될 수 있다. 따라서 결과 데이터를 저장할 메모리 공간이 충분할 때 나머지를 잡아내는 언패킹을 사용해야한다.

0개의 댓글