본문 바로가기
Python/Python

파이썬 - collections.namedtuple

by 키모형 2022. 12. 17.

튜플(tuple)은 인덱스를 통해서만 데이터에 접근할 수 있지만 네임드 튜플(named tuple)은 인덱스뿐만 아니라 키(key)로도 데이터에 접근할 수 있는 자료형이다.

collections.namedtuple()은 키값으로 데이터에 접근할 수 있는 튜플을 생성하는 함수이다.

문제

직원 주소록을 만들고자 다음과 같이 이름, 나이, 휴대전화로 구성된 직원 정보 데이터를 이용하려 한다.

data = [
    ('홍길동', 23, '01099990001'), 
    ('김철수', 31, '01099991002'), 
    ('이영희', 29, '01099992003'),
]

하지만, 리스트의 요소가 튜플이라 데이터에 접근하기가 쉽지 않다. 왜냐하면 데이터를 확인하려면 튜플 데이터의 인덱스 순서가 무엇을 뜻하는지 알아야 하기 때문이다.

이에 다음처럼 튜플 데이터를 각 칼럼의 이름으로 찾을 수 있도록 하려면 어떻게 해야 할까?

emp = data[0]  # 첫번째 직원
print(emp.name)  # "홍길동" 출력
print(emp.age)  # 23 출력
print(emp.cellphone)  # 01099990001 출력

풀이

키값으로 튜플 데이터에 접근하는 데는 다양한 방법이 있다. 일반적으로는 클래스를 이용하지만, 여기서는 가장 간단하게 해결할 수 있는 namedtuple 모듈을 사용해 보기로 한다.

먼저 다음과 같이 namedtuple 모듈을 불러온다(import).

>>> from collections import namedtuple

그리고는 다음과 같이 데이터를 선언하자.

>>> data = [
...     ('홍길동', 23, '01099990001'),
...     ('김철수', 31, '01099991002'),
...     ('이영희', 29, '01099992003'),
... ]

선언한 데이터의 형식에 맞게 다음과 같이 namedtuple 자료형을 생성하자.

>>> Employee = namedtuple('Employee', 'name, age, cellphone')

namedtuple() 함수의 첫 번째 입력은 자료형 이름(type name)이다. 보통 namedtuple()로 생성하는 객체 이름과 같도록 한다. 여기서는 Employee로 했다. 뒤에 따라오는 쉼표로 구성된 문자열 'name, age, cellphone' 은 Employee의 속성이 된다.

그리고 선언한 data의 요소인 튜플을 다음과 같이 namedtuple로 변환하자.

>>> data = [Employee(emp[0], emp[1], emp[2]) for emp in data]

리스트 컴프리헨션을 이용하여 data의 각 튜플을 모두 Employee 자료형(네임드 튜플 자료형)으로 교체했다. Employee 자료형의 _make() 함수를 사용하면 이 과정을 더 깔끔하게 처리할 수 있다.

>>> data = [Employee._make(emp) for emp in data]

튜플의 요소가 많다면 _make() 함수를 사용하는 것이 유리하다. 이제 Employee 자료형으로 변경한 데이터를 다음과 같이 사용해 보자.

>>> emp = data[0]  # 첫번째 직원
>>> emp.name
'홍길동'
>>> emp.age
23
>>> emp.cellphone
'01099990001'

이제 문제에서 요구하는 대로 인덱스가 아닌 키로 데이터를 조회할 수 있게 되었다. 참고로 네임드 튜플은 다음처럼 _asdict() 함수를 사용하면 간단하게 딕셔너리로 변환할 수 있다.

>>> emp._asdict()
{'name': '홍길동', 'age': 23, 'cellphone': '01099990001'}

또한, 네임드 튜플은 다음처럼 인덱스로 접근할 수도 있다.

>>> emp[0]
'홍길동'
>>> emp[1]
23
>>> emp[2]
'01099990001'

그리고 네임드 튜플은 값을 변경할 수 없는(immutable) 튜플의 특징을 그대로 가지므로 속성값을 변경하려고 하면 다음과 같은 오류가 발생한다.

>>> emp.name = '박길동'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

그러므로 다음처럼 _replace() 함수로만 값을 바꿀 수 있다.

>>> new_emp = emp._replace(name="박길동")
>>> new_emp
Employee(name='박길동', age=23, cellphone='01099990001')

단, _replace() 함수는 해당 객체를 직접 변경하는 것이 아니라 값을 변경한 새로운 객체를 만들어 반환한다는 점에 주의하자.

반응형

'Python > Python' 카테고리의 다른 글

pip install "패키지" 오류 발생 시 대처  (0) 2022.12.26
파이썬 - collections.Counter  (0) 2022.12.17
파이썬 - collections.deque  (0) 2022.12.17
파이썬 - datetime 라이브러리  (0) 2022.12.17
파이썬 - 내장 함수  (0) 2022.12.15