상세 컨텐츠

본문 제목

NamedTuple

개발/python-심화(Advanced)

by Matthew0633 2022. 4. 20. 22:49

본문

특정 attribute들을 가진 객체를 정의하고 싶을 때가 있다. 그런데 class (+ init함수 등등) 까지 정의하긴 부담스럽고, 또 단순한 sequence 객체를 활용했을 때, 해당 attribute들을 원소로 attribute명이 아닌 index로 접근해야해서 직관성이 떨어지는 부분을 피하고 싶은 고민을 했었다. 이 때 NamedTuple을 사용할 수 있다. 여러 attribute를 가지는 특정 namedtuple 객체를 정의하고, 이것에 attribute 값들을 넣어주면 객체들을 찍어낼 수 있다. 그리고 attribute 값을 접근할 때 namedtuple1. attr1 과 같이 attribute 명을 사용하기 때문에 코드 또한 직관성이 올라간다.

요즘은 namedtuple 보다 더 간편하고 가독성이 높은 dataclass를 더 자주 쓰게 되어 이에 대한 포스팅도 정리해볼 예정이다.

 

NamedTuple

Tuple인데 Dictionary의 성질을 가지고 있다. key로 데이터를 조회할 수도 있고, index로써 조회할 수도 있다.
Tuple 원소를 접근하는 code를 짤 때 key로서 명시했을 때 가독성이 높아진다면, NamedTuple을 활용할 수 있다.

아래는 2차원 좌표 간에 유클리드 거리를 계산하는 코드이다. NamedTuple을 활용했을 때 key로 value를 접근 가능하여, 연산에 활용하는 값이 좌표라는 것을 직관적으로 코드에 나타낼 수 있다

from math import sqrt

# 네임드 튜플 미사용
pt1, pt2 = (1.0, 5.0), (2.5, 1.5)
dist = sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2)

# 네임드 튜플 사용
from collections import namedtuple

Point = namedtuple('Point', 'x y')
pt1, pt2 = Point(*pt1), Point(*pt2)

# 연산에 활용하는 값이 x,y 좌표라는 것을 코드로 직관적으로 알 수 있다
dist = sqrt((pt2.x - pt1.x) ** 2 + (pt2.y - pt1.y) ** 2)

 

NamedTuple 선언방식 4가지와 객체 생성 방식

NamedTuple 은 list, comma, 공백을 활용한 key 문자열을 활용하여 선언할 수 있다. 그런데 key가 중복되거나, key로서 python의 reserved word를 사용할 때는 에러가 발생한다. 이 때 임의로 key가 수정되게 설정할 수 있는데 rename=True로 설정해주면 가능하다.

key의 이름으로 underscore로 시작하는 key의 이름을 사용하게 되면 에러가 발생한다

# NamedTuple 선언 방법
Point1 = namedtuple('Point', ['x', 'y']) # list 활용
Point2 = namedtuple('Point', 'x, y') # comma 활용
Point3 = namedtuple('Point', 'x y') # 공백 활용
Point4 = namedtuple('Point', 'x y x class', rename=True) # key를 임의로 rename (Default=False)

# NamedTuple 객체 생성
p1 = Point1(x=10, y=35)
p2 = Point2(20, 40)
p3 = Point3(45, y=20)
p4 = Point4(10, 20, 30, 40)
p5 = Point3(**{'x': 75, 'y': 55}) # Dict to Unpacking

# 출력
print(p1, p2, p3, p4, p5)

"""
Outputs:
Point(x=10, y=35) Point(x=20, y=40) Point(x=45, y=20) Point(x=10, y=20, _2=30, _3=40) Point(x=75, y=55)
"""

 

NamedTuple의 3개 method

  • _make() : key개수와 일치하는 원소들을 iterable 객체에 포함하여 인자로 넣어줄 때 이를 NamedTuple 객체로 생성한다
  • _fields() : NamedTuple 객체의 key 들을 확인할 수 있다
  • _asdict() : NamedTuple 객체가 가진 key-value 를 OrderedDict로 생성하여 반환한다
# _make() : 새로운 객체 생성
p4 = Point1._make([52, 38]) # key의 개수와 원소개수가 불일치 시 에러 발생

print(p4)

# _fields : 필드 네임 확인
print(p1._fields, p2._fields, p3._fields)

# _asdict() : OrderedDict 반환
print(p1._asdict(), p4._asdict())

"""
Outputs:
Point(x=52, y=38)
('x', 'y') ('x', 'y') ('x', 'y')
{'x': 10, 'y': 35} {'x': 52, 'y': 38}
"""

 

NamedTuple + List Comprehension

List Comprehension을 사용하여 효율적이고 pythonic하게 NameTuple 객체를 생성할 수 있다

numbers = [str(n) for n in range(1, 21)]
ranks = 'A B C D'.split()

# NamedTuple 선언
Classes = namedtuple('Classes', ['rank', 'number'])

# List Comprehension으로 NamedTuple 객체 생성
students = [Classes(rank, number) for rank in ranks for number in numbers]

관련글 더보기

댓글 영역