데이터 사이언스를 하다보면, 데이터를 딕셔너리 형태로 만드는 경우가 많다.
그런데 tuple형태의 자료를 다루는 것이 불가피할 때, 일반적인 튜플의 경우 key값 할당이 불가능하므로 곤란할 때가 많다.
이 때, 내장된 collections 패키지의 namedtuple은 유용한 기능을 수행한다.
tuple로 정렬된 여러 x,y좌표들에 대해 거리를 계산하는 공식을 만들었다고 가정하자. 일반적인 tuple로 값을 할당하여 계산 로직을 짜면 아래와 같이 코드가 작성 될 것이다.
일반적인 tuple
pt1 = (1.0, 5.0)
pt2 = (2.5, 1.5)
from math import sqrt
line_length = sqrt((pt2[0] - pt1[0]) ** 2 + (pt2[1] - pt1[1]) ** 2)
print(line_length)
해당 코드는 Python의 장점을 하나도 이용하지 못하고 있는데, 객체에 값을 일일히 할당해 주어야 한다는 점과 indexing이 변하지 않을 것임을 가정하고 있다는 점 때문이다.
이는 재사용성을 떨어뜨릴 뿐더러, 데이터의 변동에도 취약하다.
namedtuple 응용하기
Point = namedtuple('Point', 'x y')
pt1 = Point(1.0, 5.0)
pt2 = Point(2.5, 1.5)
line_length = sqrt((pt2.x - pt1.x) ** 2 + (pt2.y - pt1.y) ** 2)
print(line_length)
위 예시는 같은 로직을 namedtuple을 이용하여 설계한 예시이다.
각각의 key값을 x, y로 하는 namedtuple 객체를 생성하여 해당 객체에 값을 입력한다.
이는 튜플 정보가 Class처럼 저장된다는 의미로, Python의 장점을 잘 활용하는 예시이다.
더불어 일반적인 tuple에서 indexing이 고정된 색인을 이용하는 것과 달리, namedtuple에서는 key값을 이용하므로 값의 변동이나 인식에 탁월한 강점을 지닌다.
namedtuple 선언하기
namedtuple을 선언하는 방식으로, 공식 문서에서는 네 가지 방식을 제안한다.
# list로 각각의 key 할당하기
Point1 = namedtuple('Point', ['x', 'y'])
# 문자열 안의 comma 구분자로 각각의 key 할당하기
Point2 = namedtuple('Point', 'x, y')
# 문자열 안의 띄어쓰기 구분자로 각각의 key 할당하기
Point3 = namedtuple('Point', 'x y')
# 문자열 안에 중복이 존재할 경우 rename메서드로 자체적인 key 할당하기
Point4 = namedtuple('Point', 'x y x class', rename=True)
이에 값을 할당하여 각각을 출력해보면 아래와 같은 결과물이 나온다.
p1 = Point1(x=10, y=35)
p2 = Point2(20, 40)
p3 = Point3(45, y=20)
p4 = Point4(10, 20, 30, 40)
print("Point들 출력해보기: ", p1, p2, p3, p4)
Point들 출력해보기: Point(x=10, y=35) Point(x=20, y=40) Point(x=45, y=20) Point(x=10, y=20, _2=30, _3=40)
namedtuple unpacking
1. value unpacking
값을 일일히 할당하고 싶을 때에는 key 개수만큼 지정하여 할당해주면 된다.
# Unpacking
x, y= p3 # 각각을 알아서 대응하여 값을 할당해줌.
print(p3)
print(x, y)
Point(x=45, y=20)
45 20
2. dictionary unpacking
단순히 namedtuple객체(dictionary)의 형태로 지정한다고 해서 값이 할당되지 않는다.
따라서 같은 key값을 가진 dictionary를 namedtuple로 변환할 때에는 요령이 필요한데, **kwarg 형태로 넣어주어야 한다는 점이 그것이다.
# 같은 key값을 가지는 dictionary를 지정된 namedtuple객체로 변환하기
temp_dict = {'x':75, 'y':30}
print(Point3(**temp_dict))
Point(x=75, y=30)
namedtuple객체의 메서드들
1. _make()
namedtuple로 할당된 새로운 객체를 생성한다.
p4 = Point1._make(temp)
print(p4)
Point(x=52, y=38)
2. _fields
namedtuple 객체의 필드 이름을 확인한다.
print(p1._fields, p2._fields, p3._fields)
('x', 'y') ('x', 'y') ('x', 'y')
3. _asdict()
OrderedDict객체로 변환하는 메서드이다.
반환된 OrderedDict객체는 dict 함수로 dictionary 지정하여 유연하게 사용 가능하다.
print(p1._asdict(), p4._asdict())
print(dict(p1._asdict()))
OrderedDict([('x', 10), ('y', 35)]) OrderedDict([('x', 52), ('y', 38)])
{'x': 10, 'y': 35}
4. _replace()
수정된 새로운 객체를 반환한다.
이 때 새로운 객체라는 것은, 다른 memory를 할당하는 새로운 객체를 생성한다는 의미이다.
print(p2._replace(y=100))
Point(x=20, y=100)
'Python > 알고리즘' 카테고리의 다른 글
[자료구조] 그래프 DFS/BFS Python pseudo코드로 이해하기 (0) | 2022.02.15 |
---|---|
N개의 연속된 자연수 리스트에서 인접하지 않은 m개 뽑기 (0) | 2022.02.14 |
Python의 concurrent.futures 활용하여 병렬 실행 결과 return하기 (0) | 2021.07.25 |
Python 내장 패키지 itertools 도장깨기 (0) | 2021.07.05 |