728x90
언패킹 기본
- 기본 언패킹의 한계점은 언패킹할 시퀀스의 길이를 미리 알고 있어야 한다는 것이다.
- 아래와 같이 언패킹을 시도할 경우 에러가 발생할 것이다.
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
- 물론 이를 해결하기 위해 슬라이싱 방식을 사용하기도 한다.
- 이 방식도 부분적으로 배열 길이로 인해 인덱스 예외가 발생할 수 있다.
oldest = car_ages_descending[0]
second_oldest = car_ages_descending[1]
others = car_ages_descending[2:]
print(oldest, second_oldest, others)
별표 식을 통한 언패킹
별표 식 언패킹 기본
- 파이썬은 이런 케이스를 다루기 위해 별표 식을 사용하여 이를 방지할 수 있다.
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) # 20 0 [19, 15, 9, 8, 7, 6, 4, 1]
*others, second_youngest, youngest = car_ages_descending
print(youngest, second_youngest, others) # 0 1 [20, 19, 15, 9, 8, 7, 6, 4]
- 별표 식만 사용하여 언패킹은 불가능하다.
- 또한 두개 이상의 별표 식은 불가능하다.
- 아래 두 케이스 다 에러가 발생한다.
*others = car_ages_descending
first, *middle, *second_middle, last = [1, 2, 3, 4]
별표 식 계층형 자료 구조 언패킹
- 아래와 같이 계층형 구조가 있을 때도 활용 가능하다.
- 언패킹 시 항상
list
인스턴스가 된다. - 또한 남은 원소가 없을 경우 빈 리스트가 반환된다.
car_inventory = {
'시내': ('그랜저', '아반테', '티코'),
'공항': ('제네시스 쿠페', '소나타', 'K5', '악센트'),
}
((loc1, (best1, *rest1)),
(loc2, (best2, *rest2))) = car_inventory.items()
print(f'{loc1} 최고는 {best1}, 나머지는 {len(rest1)} 종') # 시내 최고는 그랜저, 나머지는 2종
print(f'{loc2} 최고는 {best2}, 나머지는 {len(rest2)} 종') # 공항 최고는 제네시스 쿠페, 나머지는 3종
별표 식의 주의점
- 별표 식은 항상 리스트를 만들어내기 때문에 이터레이터를 별표 식으로 언패킹하면 메모리를 모두 다 사용해서 프로그램이 멈출 수 있다.
- 따라서 결과 데이터가 모두 메모리에 들어갈 수 있다고 확신할 때만 나머지를 모두 잡아내는 언패킹을 사용해야 한다.
- 이 내용은 특히 대량의 데이터를 처리하거나 메모리 사용량이 중요한 애플리케이션을 개발할 때 신경 써야 할 중요한 사항이다.
이터레이터를 별표 식으로 언패킹
def generate_numbers():
for i in range(10**6):
yield i
gen = generate_numbers()
first, *rest = gen
- 위 코드에서는
gen
이 1,000,000개의 숫자를 생성하는 제너레이터다. 이 제너레이터는 한 번에 하나의 값을 생성하여 메모리를 적게 사용해야 하지만,*rest
로 언패킹하는 순간, 모든 값이 리스트에 담겨서 메모리로 로드되므로 매우 비효율적이다. - 이 경우 메모리 사용량이 커질 수 있으며, 데이터 크기가 매우 큰 경우에는 프로그램이 메모리 부족으로 멈출 수 있다.
해결 방법
- 이터레이터를 별표 식으로 언패킹하지 않기:
- 이터레이터에서 필요한 값만 사용하고 나머지는 무시하거나, 메모리에 부담을 주지 않도록 제너레이터 표현식이나 for 루프를 통해 값을 하나씩 처리한다.
- itertools를 활용한 부분 처리:
- Python 표준 라이브러리인
itertools
모듈을 사용하면, 이터레이터를 메모리 효율적으로 처리할 수 있다. - 예를 들어,
islice
함수를 사용하여 이터레이터의 일부만 처리하거나, 필요한 부분만 읽을 수 있다.
- Python 표준 라이브러리인
from itertools import islice
gen = generate_numbers()
first = next(gen)
rest = islice(gen, 10) # 처음 10개 요소만 가져옴
이 코드는 이터레이터에서 첫 번째 값을 first
로 가져오고, islice
를 사용해 나머지 10개의 값만 처리하여 메모리 사용량을 줄인다.
728x90
'Programming Language > Python' 카테고리의 다른 글
BETTER WAY 15 - 딕셔너리 삽입 순서에 의존할 떄는 조심하라 (2) | 2024.11.11 |
---|---|
BETTER WAY 14 - 복잡한 기준을 사용해 정렬할 때는 key 파라미터를 사용하라 (0) | 2024.10.14 |
BETTER WAY 12 - 스트라이드와 슬라이스를 한 식에 함께 사용하지 말라 (0) | 2024.09.20 |
BETTER WAY 10 - 대입식을 사용해 반복을 피하라 (1) | 2024.09.12 |
BETTER WAY 8 - 여러 이터레이터에 대해 나란히 루프를 수행하려면 zip을 사용하라 (0) | 2024.09.09 |