1. NamedTuple이란?
NamedTuple은 Python의 collections 모듈에서 제공하는 클래스의 서브타입으로, 튜플의 장점(불변성과 간결한 데이터 구조)을 유지하면서도 각 요소에 이름을 부여하여 코드의 가독성과 유지보수성을 높여줍니다. 이를 통해 인덱스 번호 대신 이름으로 데이터에 접근할 수 있어 직관적인 코드를 작성할 수 있습니다.
주요 특징:
• 불변성: 일반 튜플처럼 생성 후 변경이 불가능합니다.
• 키 접근 지원: 이름으로 데이터 접근이 가능합니다.
• 간결한 데이터 구조: 가벼운 클래스처럼 동작합니다.
2. 일반 튜플의 단점
일반 튜플은 인덱스 번호로 데이터를 접근해야 합니다. 이는 데이터의 의미를 파악하기 어렵게 만들고, 코드의 가독성을 저하시킬 수 있습니다.
point = (10, 20)
# 인덱스를 사용해야만 데이터에 접근 가능
print(point[0]) # 10
print(point[1]) # 20
위 코드는 숫자 10과 20이 무엇을 나타내는지 파악하기 어렵습니다. 인덱스 번호에 의존하면 실수로 잘못된 데이터를 참조할 가능성도 높아집니다.
또한, 일반 튜플은 단순히 값의 모음이므로, 데이터의 의미를 명시적으로 나타낼 수 없습니다. 이는 특히 복잡한 데이터 구조를 다룰 때 문제가 됩니다.
person = ("Alice", 30, "Engineer")
# person[0], person[1], person[2]만으로는 의미를 알기 어려움
데이터의 구조가 변경되었을 때, 일반 튜플은 인덱스를 사용하는 모든 코드를 수정해야 합니다. 반면, NamedTuple은 이름 기반 접근 덕분에 코드 수정 범위가 줄어듭니다.
# 일반 튜플
point = (10, 20)
point = (10, 20, 30) # 필드 추가 시 기존 코드 전면 수정 필요
# NamedTuple
Point = namedtuple('Point', ['x', 'y', 'z'])
point = Point(10, 20, 30)
print(point.z) # 추가된 필드도 쉽게 접근 가능
일반 튜플은 요소에 대한 타입 정보를 명시적으로 제공할 수 없습니다. 이는 코드 작성 시 타입 안정성을 확보하기 어렵게 만듭니다.
# 일반 튜플
point = (10, 20) # x와 y가 숫자인지 보장할 수 없음
# NamedTuple은 타입 힌트 제공
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
3. 다양한 선언법
아래와 같이 다양한 방법으로 선언 가능합니다.
from collections import namedtuple
#기본선언
Point = namedtuple('Point',['x','y'])
Point = namedtuple('Point','x,y')
Point = namedtuple('Point','x y')
Point = namedtuple('Point','x y x class', renmae = True)
# x의 경우 키중복이 허용되지 않고, class의 경우 예약어이므로 사용이 불가하지만,
# rename=True 키워드와 함께 사용가능합니다.
# 인스턴스 생성
p = Point(10, 20)
print(p.x, p.y) # 출력: 10 20
기본값을 포함하여 선언할 수도 있습니다.
Point = namedtuple('Point', ['x', 'y'], defaults=[0, 0])
# 기본값 사용
p1 = Point() # x=0, y=0
p2 = Point(10) # x=10, y=0
print(p1, p2) # 출력: Point(x=0, y=0) Point(x=10, y=0)
타입 힌트를 포함한 선언 (typing.NamedTuple)도 가능합니다.
from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int
p = Point(10, 20)
print(p.x, p.y) # 출력: 10 20
4. 사용 방법
아래와 같이 다양한 방식으로 사용가능합니다.
# 방법1
p = Point(10, 20)
print(p.x, p.y) # 출력: 10 20
# 방법2
p = Point(x=10, y=20)
print(p.x, p.y) # 출력: 10 20
# 방법3
data_dict = {'x':10, 'y':20}
p = Point(**data_dict)
print(p.x, p.y) # 출력: 10 20
#unpacking
x, y = p
print(x, y) # 출력: 10 20
5. 메소드
필드 정보 확인
print(Point._fields) # 출력: ('x', 'y')
새로운 값으로 업데이트
p = p._replace(x=30)
print(p) # 출력: Point(x=30, y=20)
딕셔너리로 변환
print(p._asdict()) # 출력: {'x': 30, 'y': 20}
형 변환
일반 튜플이나 딕셔너리와 상호 변환이 가능합니다.
new_p = Point._make([40, 50])
print(new_p) # 출력: Point(x=40, y=50)
4. 결론
NamedTuple은 데이터 구조를 간결하고 명확하게 관리할 수 있는 강력한 도구입니다. 특히, 이름 기반 접근과 타입 힌트의 조합은 유지보수성과 코드 안정성을 크게 향상시킵니다. 데이터가 고정된 구조로 설계되었을 때, 클래스 대신 NamedTuple을 사용하면 가독성과 성능을 동시에 확보할 수 있습니다.