튜플(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 모듈을 사용해 문제를 풀면 아래처럼 시도할 수 있다
from collections import namedtuple
data = [
('홍길동', 23, '01099990001'),
('김철수', 31, '01099991002'),
('이영희', 29, '01099992003'),
]
Employee = namedtuple('Employee', 'name, age, cellphone')
data = [Employee(emp[0], emp[1], emp[2]) for emp in data] #고 선언한 data의 요소인 튜플을 namedtuple로 변환
data = [Employee._make(emp) for emp in data] #리스트 컴프리헨션을 이용하여 data의 각 튜플을 모두 Employee 자료형(네임드 튜플 자료형)으로 교체
emp = data[0]
print(emp.name) #홍길동
print(emp.age) #23
print(emp.cellphone) #'01099990001'
namedtuple() 함수의 첫 번째 입력은 자료형 이름(type name)이다. 보통 namedtuple()로 생성하는 객체 이름과 같도록 한다. 여기서는 Employee로 했다. 뒤에 따라오는 쉼표로 구성된 문자열 'name, age, cellphone' 은 Employee의 속성이 된다
Employee 자료형의 _make() 함수를 사용하면 data의 각 튜플을 모두 Employee 자료형(네임드 튜플 자료형)으로 교체하는 과정을 더 깔끔하게 처리할 수 있다. 튜플의 요소가 많다면 _make() 함수를 사용하는 것이 좋다
네임드 튜플은 _asdict() 함수를 사용하면 간단하게 딕셔너리로 변환할 수 있고, 인덱스로 접근할 수도 있다
📌 네임드 튜플은 값을 변경할 수 없는(immutable) 튜플의 특징을 그대로 가지므로 속성값을 변경하려고 하면 오류가 발생한다
>>> emp.name = '박길동'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
어래 문장의 문자열을 이용하여 다음처럼 사용한 문자(key)와 해당 문자의 사용 횟수(value)를 딕셔너리로 만들려면 어떻게 해야 할까? 단, 공백 등 특수 문자도 포함하며 대소문자는 구분하기로 한다
Life is too short, You need python.
{'L': 1, 'i': 2, 'f': 1, 'e': 3, ' ': 6, 's': 2, 't': 3, 'o': 5, 'h': 2, 'r': 1, ',': 1, 'Y': 1, 'u': 1, 'n': 2, 'd': 1, 'p': 1, 'y': 1, '.': 1}
from collections import defaultdict
text = "Life is too short, You need python."
d = defaultdict(int)
for c in text:
d[c] += 1
print(dict(d))
딕셔너리로 집계용 코드를 작성할 때는 항상 초깃값에 신경 써야 한다. 하지만 collections의 defaultdict를 사용하면 이러한 번거로움을 줄일 수 있다
👉 코드 풀이: defaultdict()의 인수로 int를 전달하여 딕셔너리 d를 생성했다. int를 기준으로 생성한 딕셔너리 d의 값은 항상 0으로 자동 초기화되므로 초기화를 위한 별도의 코드가 필요 없다. defaultdict()의 인수로는 int 외에도 list 등 여러 자료형을 사용할 수 있다