파이썬에는 값으로 이루어진 불변 순서쌍을 만들어낼 수 있는 tuple 내장 타입이 존재한다. 튜플은 숫자 인덱스를 사용해 접근할 수 있고, 인덱스를 통해 새 값을 대입하는 식으로 튜플을 변경할 수는 없다.
언패킹(unpacking)
파이썬에는 언패킹(unpacking)구문이 존재한다. 언패킹 구문을 사용하면 한 문장 안에서 여러 값을 대입할 수 있다. 언패킹 구문에 사용된 패턴은 튜플을 변경하려고 시도할 때 사용한 구문, 즉 파이썬이 허용하지 않았던 구문과 비슷하지만 매우 다르게 작동한다.
예를 들어 튜플이 쌍이라는 사실을 알고 있으면 인덱스를 사용해 각 값에 접근하는 대신 이 튜플을 두 변수 이름으로 이루어진 튜플에 대입할 수 있다.
item = ('호박엿', '식혜')
first, second = item # 언패킹
print(first, '&', second)
>>>
호박엿 & 식혜
언패킹은 튜플 인덱스를 사용하는 것보다 시각적인 잡음이 적다. 리스트, 시퀀스, 이터러블(반복 가능한 객체) 안에 여러 계층으로 이터러블이 들어간 경우 등 다양한 패턴을 언패킹 구문에 사용할 수 있다. 다음과 같이 코드를 작성하는 것이 별로 추천되지는 않지만 이런 코드도 가능하다.
favorite_snacks = {'과자' : ('오뜨', 100), '음식' : ('닭강정', 200), '채소' : ('당근', 20)}
((type1, (name1, cals1)), (type2, (name2, cals2)), (type3, (name3, cals3))) = favorite_snacks.items()
print(f'제일 좋아하는 {type1}는(은) {name1}, {cals1} 칼로리입니다.')
print(f'제일 좋아하는 {type2}는(은) {name2}, {cals2} 칼로리입니다.')
print(f'제일 좋아하는 {type3}는(은) {name3}, {cals3} 칼로리입니다.')
>>>
제일 좋아하는 과자는(은) 오뜨, 100 칼로리입니다.
제일 좋아하는 음식는(은) 닭강정, 200 칼로리입니다.
제일 좋아하는 채소는(은) 당근, 20 칼로리입니다.
파이썬 초보자는 언패킹을 사용하면 임시 변수를 사용하지 않고도 값을 맞바꿀 수 있다는 사실에 놀랄지도 모른다. 아래 예시를 보자.
# 전통적인 C 스타일
def swap(a, b):
tmp = a
a = b
b = tmp
# 파이썬 스타일
def swap(a, b):
a, b = b, a
a = '빨강'
b = '검정'
C 스타일에서는 임시 변수를 선언해 a를 대입하고, a에 b를 대입하고 b에 tmp를 대입하는 식으로 복잡하지만 언패킹 구문을 사용하면 위와 같이 한 줄로 줄일 수 있다.
어떻게 이런 맞바꾸기가 가능한지 살펴보자.
우선 대입문의 우항(b, a)이 계산되고, 그 결괏값이 이름이 없는 새로운 tuple에 저장된다.
그 후 대입문의 좌항에 있는 언패킹 패턴(a, b)을 통해 임시 tuple에 있는 값이 a와 b라는 변수에 각각 저장된다.
따라서 0번 인덱스의 빨강은 파랑으로 바뀌고, 1번 인덱스의 파랑은 빨강으로 바뀐 뒤 이름이 없는 임시 tuple이 사라진다.
언패킹의 용도 중 또 쓸모 있는 것으로 for 루프 또는 그와 비슷한 다른 요소의 대상인 리스트의 원소를 언패킹하는 것이 있다. 추후 다시 포스팅할 기회가 있을 것이지만 간단하게 살펴보자.
먼저 언패킹을 사용하지 않고 음식이 들어있는 리스트에 대해 이터레이션(iteration)하는 코드를 살펴보자.
snacks = [('오뜨', 100), ('닭강정', 200), ('당근', 20)]
for i in range(len(snacks)):
item = snacks[i]
name = item[0]
calories = item[1]
print(f'@{i+1}: {name}는(은) {calories} 칼로리입니다.')
>>>
@1: 오뜨는(은) 100 칼로리입니다.
@2: 닭강정는(은) 200 칼로리입니다.
@3: 당근는(은) 20 칼로리입니다.
잘 작동하지만 snacks 구조 내부의 데이터를 인덱스로 찾으려 하니 코드가 길어진다. 다음 예제를 살펴보자.
snacks = [('오뜨', 100), ('닭강정', 200), ('당근', 20)]
for rank, (name, calories) in enumerate(snacks, 1):
print(f'@{rank}: {name}는(은) {calories} 칼로리입니다.')
>>>
@1: 오뜨는(은) 100 칼로리입니다.
@2: 닭강정는(은) 200 칼로리입니다.
@3: 당근는(은) 20 칼로리입니다.
enumerate 내장 함수로 언패킹을 활용하니 훨씬 간단하게 구현이 가능하다. 이런 방식이 진정한 파이썬다운 방식이다.
파이썬은 list 구조, 함수 인자, 키워드 인자, 다중 반환 값에 대한 언패킹 기능도 제공한다. 추후에 포스팅할 기회가 있을 것이다.
참고
- 파이썬 코딩의 기술 - 똑똑하게 코딩하는 법, 브렛 슬라킨 저/오현석 역
'◎ Python > 코딩의 기술 (책)' 카테고리의 다른 글
[코딩의 기술] 7. range보다는 enumerate를 사용하라 (0) | 2023.04.30 |
---|---|
[코딩의 기술] 5. 복잡한 식을 쓰는 대신 도우미(헬퍼) 함수를 작성하자 (0) | 2022.11.29 |
[코딩의 기술] 4. f-문자열을 통한 인터폴레이션을 사용하라 (1) | 2022.11.28 |
[코딩의 기술] 3. bytes와 str의 차이를 알자 (0) | 2022.11.27 |
[코딩의 기술] 2. PEP 8 스타일 가이드를 따르자 (2) | 2022.09.15 |
자기계발 블로그