TIL10. Python : NamedTuple ์ด๋ž€?

ID์งฑ์žฌยท2021๋…„ 9์›” 10์ผ
0

Python

๋ชฉ๋ก ๋ณด๊ธฐ
22/39
post-thumbnail

๐Ÿ“Œ ์ด ํฌ์ŠคํŒ…์—์„œ๋Š” Python์˜ NamedTuple์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์™€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.



๐ŸŒˆ NamedTuple

๐Ÿ”ฅ namedtuple์„ ์™œ ์“ธ๊นŒ์š”?

๐Ÿ”ฅ namedtuple ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ๊นŒ?

๐Ÿ”ฅ namedtuple์˜ ๋งค์„œ๋“œ ์ •๋ฆฌ

๐Ÿ”ฅ namedtuple ํ™œ์šฉ ์˜ˆ์‹œ



1. namedTuple์„ ์™œ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€?

๐Ÿค” namedTuple ์ด๋ž€?

โœ”๏ธ ๋„ค์ž„๋“œํŠœํ”Œ์€ ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜ ๋“ฏ์ด ํŠœํ”Œ์„ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ์›์†Œ์— ์ด๋ฆ„์œผ๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•œ ํŠœํ”Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
โœ”๏ธ ์ฆ‰, ๋ฐ์ดํ„ฐ์˜ ๊ฐ’์„ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด ํŠœํ”Œ์˜ ๊ฐ’์— ์ด๋ฆ„์œผ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜ ํŠœํ”Œ์ด ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์— ๋น„ํ•ด ์ง๊ด€์ ์ž…๋‹ˆ๋‹ค.
โœ”๏ธ ๋˜ํ•œ ๋„ค์ž„๋“œํŠœํ”Œ์€ ์ผ๋ฐ˜ ๊ฐ์ฒด ํ˜•ํƒœ๋ณด๋‹ค ์ ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๋‹ค์–‘ํ•œ ์ ‘๊ทผ๋ฒ•์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
โœ”๏ธ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ ์ผ๋ฐ˜์ ์ธ ์ƒํ™ฉ์—์„œ ๋ฆฌ์ŠคํŠธ๋ณด๋‹ค ํŠœํ”Œ์ด ์ข‹๊ณ , ํŠœํ”Œ๋ณด๋‹ค ๋„ค์ž„๋“œํŠœํ”Œ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๐Ÿค” ๋‘ ์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ ๊ตฌํ•˜๊ธฐ ๋ฌธ์ œ

โœ”๏ธ ๋‘ ์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋Š” ๊ณต์‹์„ ์˜ˆ๋กœ ๋“ค์–ด, ์ผ๋ฐ˜ํŠœํ”Œ๊ณผ ๋„ค์ž„๋“œํŠœํ”Œ์˜ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‘ ์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๋Š” ์•„๋ž˜ ๊ณต์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ”๏ธ ์ผ๋ฐ˜ ํŠœํ”Œ์€ ์ธ๋ฑ์Šค ๋ฒˆํ˜ธ๋กœ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์„ ์ง๊ด€์ ์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์›Œ ๊ฐ’์„ ์™ธ์šฐ๊ณ  ์žˆ์–ด์•ผํ•˜๊ฑฐ๋‚˜, ์ฃผ์„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

from math import sqrt
point1 = (1.0, 5.0) # x1=1.0, y1=5.0
point2 = (2.5, 1.5) # x2=2.5, y2=1.5
line_len = sqrt((point2[0]-point1[0]) ** 2 + (point2[1]-point1[1]) ** 2)
print(line_len) # 3.8078865529319543

โœ”๏ธ ์ด์— ๋ฐ˜ํ•ด, namedtuple์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ๋ณ€์ˆ˜๊ฐ€ ๊ฐ€๋ฅดํ‚ค๋Š” ๊ฐ’์„ ๋ณด๋‹ค ์ง๊ด€์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ namedtuple์€ ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ๋„ค์ž„๋“œํŠœํ”Œ์€ ์ด๋ฆ„์„ ๊ฐ€์ง„ tuple์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์— tuple์˜ ๊ฐ ์š”์†Œ์— ๋ ˆ์ด๋ธ”์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ๋„ค์ž„๋“œํŠœํ”Œ์€ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ง€์›ํ•˜๋Š” collections ๋‚ด์— ์กด์žฌํ•˜๊ณ , ๊ฐ์ฒด์ฒ˜๋Ÿผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

from math import sqrt
from collections import namedtuple # ๐Ÿ‘ˆ "namedtuple" import
Point = namedtuple('Point', 'x y') # ๐Ÿ‘ˆ namedtuple ์„ ์–ธ
point1 = Point(1.0, 5.0)
point2 = Point(2.5, 1.5)
line_len = sqrt((point2.x-point1.x) ** 2 + (point2.y-point1.y) ** 2)
print(line_len) # 3.8078865529319543


2. namedtuple ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ๊นŒ?

๐Ÿค” nametuple ์„ ์–ธ ๋ฐฉ๋ฒ•

โœ”๏ธ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ๋ณ€์ˆ˜ ์„ ์–ธ : ๐Ÿ” Point1 = namedtuple('Point', ['x', 'y'])
โœ”๏ธ ์ฝค๋งˆ ์‚ฝ์ž…์œผ๋กœ ์„ ์–ธ : ๐Ÿ” Point2 = namedtuple('Point', 'x, y')
โœ”๏ธ ๋„์–ด์“ฐ๊ธฐ ์‚ฝ์ž…์œผ๋กœ ์„ ์–ธ : ๐Ÿ” Point3 = namedtuple('Point', 'x y')
โœ”๏ธ rename ์˜ต์…˜ ์‚ฌ์šฉ : ๐Ÿ” Point4 = namedtuple('Point', 'x y x class', rename=True)

# ๋„ค์ž„๋“œ ํŠœํ”Œ ์„ ์–ธ ๋ฐฉ๋ฒ•
Point1 = namedtuple('Point',['x', 'y'])
Point2 = namedtuple('Point', 'x, y')
Point3 = namedtuple('Point', 'x y')
Point4 = namedtuple('Point', 'x y x class', rename=True) # default๋Š” False์ž„
print(Point1, Point2, Point3, Point4) # <class '__main__.Point'> <class '__main__.Point'> <class '__main__.Point'> <class '__main__.Point'>

๐Ÿค” rename ์˜ต์…˜์ด๋ž€?

โœ”๏ธ namedTuple ๋˜ํ•œ tuple์ฒ˜๋Ÿผ ๋ถˆ๋ณ€์˜ ํŠน์„ฑ์„ ์ง€๋‹ˆ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต๋  ์ˆ˜ ์—†๊ณ , ๋‹น์—ฐํžˆ "class"์™€ ๊ฐ™์€ ์˜ˆ์•ฝ์–ด ๋“ค์€ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์ง€์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์€ code๋Š” x๊ฐ’์ด ์ค‘๋ณต๋˜์–ด ์žˆ๊ณ , class๋ผ๋Š” ์˜ˆ์•ฝ์–ด๊ฐ€ ์„ ์–ธ ์‹œ ์‚ฌ์šฉ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

  • ๐Ÿ”Ž Point4 = namedtuple('Point', 'x y x class') ๐Ÿ‘ˆ x์ค‘๋ณต, class ์˜ˆ์•ฝ์–ด

โœ”๏ธ ์ด๋Ÿด ๊ฒฝ์šฐ, rename ์˜ต์…˜์„ True๋กœ ํ™œ์„ฑํ™”ํ•˜๋ฉด ์ค‘๋ณต๋˜๋Š” ๊ฐ’ ๋˜๋Š” ์˜ˆ์•ฝ์–ด ๋“ฑ์˜ ์ž˜๋ชป๋œ ๋ณ€์ˆ˜๋กœ ์„ ์–ธ ์‹œ ์‚ฌ์šฉํ•ด๋„ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ , ๋žœ๋คํ•œ ๋ณ€์ˆ˜์— ๋ฐ์ดํ„ฐ๋ฅผ ํ• ๋‹นํ•ด์ค๋‹ˆ๋‹ค.
โœ”๏ธ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ ๋”๋ธ”์•„์Šคํƒ€(**)๋ฅผ ์‚ฌ์šฉํ•ด ๋”•์…”๋„ˆ๋ฆฌ์˜ ํ˜•ํƒœ๋„ ์–ธํŒฉํ‚น ํ•ด์ค๋‹ˆ๋‹ค.

# ๋„ค์ž„๋“œ ํŠœํ”Œ ์„ ์–ธ ๋ฐฉ๋ฒ•
Point1 = namedtuple('Point',['x', 'y'])
Point2 = namedtuple('Point', 'x, y')
Point3 = namedtuple('Point', 'x y')
Point4 = namedtuple('Point', 'x y x class', rename=True) # ๐Ÿ‘ˆ default๋Š” False์ž…๋‹ˆ๋‹ค.
p1 = Point1(x=10, y=35)
print(p1) # Point(x=10, y=35)
p2 = Point2(20, 40)
print(p2) # Point(x=20, y=40)
p3 = Point3(45, y=20)
print(p3) # Point(x=45, y=20)
p4 = Point4(10, 20, 30, 40)
print(p4) # Point(x=10, y=20, _2=30, _3=40) ๐Ÿ‘ˆ ์ž๋™์œผ๋กœ renameํ•ด์ค๋‹ˆ๋‹ค:)
# ๋”•์…”๋„ˆ๋ฆฌ ์–ธํŒฉํ‚น
temp_dict = {'x':75, 'y':55} 
p5 = Point1(**temp_dict) # ๐Ÿ‘ˆ ๋”•์…”๋„ˆ๋ฆฌ ์–ธํŒฉํ‚น
print(p5) # Point(x=75, y=55)
# unpacking ํ™œ์šฉ
x, y = p3
print(x+y) # 65


3. namedtuple์˜ ๋งค์„œ๋“œ ์ •๋ฆฌ

๐Ÿค” _make() : ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ

Point1 = namedtuple('Point', ['x', 'y'])
temp = [52, 38]
p4 = Point1._make(temp)
print(p4) # Point(x=52, y=38)

๐Ÿค” _fields() : ํ•„๋“œ ๋„ค์ž„ ํ™•์ธ

Point1 = namedtuple('Point', ['x', 'y'])
Point2 = namedtuple('Point', 'x, y')
Point3 = namedtuple('Point', 'x y')
print(p1._fields, p2._fields, p3._fields,) # ('x', 'y') ('x', 'y') ('x', 'y')

๐Ÿค” _asdict() : ๋”•์…”๋„ˆ๋ฆฌ๋กœ ๋ณ€ํ™˜

Point1 = namedtuple('Point', ['x', 'y'])
p1 = Point1(x=10, y=35)
temp = [52, 38]
p4 = Point1._make(temp)
print(p1._asdict(), p4._asdict()) # {'x': 10, 'y': 35} {'x': 52, 'y': 38}
print(type(p1._asdict()), type(p4._asdict())) # <class 'dict'> <class 'dict'>

๐Ÿค” _replace() : ๋„ค์ž„๋“œํŠœํ”Œ ๋˜ํ•œ ๋ถˆ๋ณ€์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ’์„ ์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ด์— ์ˆ˜์ •๋œ "์ƒˆ๋กœ์šด" ๊ฐ์ฒด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

Point2 = namedtuple('Point', 'x, y')
p2 = Point2(20, 40)
print(p2) # Point(x=20, y=40)
print(p2._replace(y=100)) # Point(x=20, y=100)


4. namedtuple ํ™œ์šฉ ์˜ˆ์‹œ

๐Ÿค” ํ•™๊ธ‰ ๊ตฌ์„ฑ์€ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค!

โœ”๏ธ 4๊ฐœ์˜ ๋ฐ˜(A,B,C,D)์— ๊ฐ 20๋ช…์˜ ํ•™์ƒ์ด ์žˆ์„ ๋•Œ ํ•™์ƒ ์ „์ฒด ๊ทธ๋ฃน ์ƒ์„ฑ
โœ”๏ธ 1๋ฒˆ๋ถ€ํ„ฐ 20๋ฒˆ๊นŒ์ง€ ํ•™์ƒ ์ƒ์„ฑ : ๐Ÿ” numbers = [str(n) for n in range(1,21)]
โœ”๏ธ 4๊ฐœ์˜ ๋ฐ˜ ์ƒ์„ฑ : ๐Ÿ” ranks = 'A B C D'.split()

# 4๊ฐœ์˜ ๋ฐ˜์— A,B,C,D์˜ ๊ฐ 20๋ช…์˜ ํ•™์ƒ์ด ์žˆ์„ ๋•Œ ํ•™์ƒ ์ „์ฒด ๊ทธ๋ฃน ์ƒ์„ฑ
from collections import namedtuple
numbers = [str(n) for n in range(1,21)] # ['1', '2', '3', '4', ...... '17', '18', '19', '20']
ranks = 'A B C D'.split() # ['A', 'B', 'C', 'D']
Classes = namedtuple('Classes', ['rank', 'number']) # ๊ฐ์ฒด๋ช…(classes)๊ณผ ๋ณ€์ˆ˜๋ช…(classes)์„ ์ผ์น˜์‹œํ‚ค๋Š”๊ฒŒ ๊ด€๋ก€์ž„
students = [Classes(rank, number) for rank in ranks for number in numbers]
print(len(students)) # 80
print(students)
"""
[Classes(rank='A', number='1'), Classes(rank='A', number='2'), Classes(rank='A', number='3'), Classes(rank='A', number='4'), 
Classes(rank='A', number='5'), Classes(rank='A', number='6'), Classes(rank='A', number='7'), Classes(rank='A', number='8'), 
Classes(rank='A', number='9'), Classes(rank='A', number='10'), Classes(rank='A', number='11'), Classes(rank='A', number='12'), 
Classes(rank='A', number='13'), Classes(rank='A', number='14'), Classes(rank='A', number='15'), Classes(rank='A', number='16'), 
Classes(rank='A', number='17'), Classes(rank='A', number='18'), Classes(rank='A', number='19'), Classes(rank='A', number='20'), 
Classes(rank='B', number='1'), Classes(rank='B', number='2'), Classes(rank='B', number='3'), Classes(rank='B', number='4'), 
Classes(rank='B', number='5'), Classes(rank='B', number='6'), Classes(rank='B', number='7'), Classes(rank='B', number='8'), 
Classes(rank='B', number='9'), Classes(rank='B', number='10'), Classes(rank='B', number='11'), Classes(rank='B', number='12'), 
Classes(rank='B', number='13'), Classes(rank='B', number='14'), Classes(rank='B', number='15'), Classes(rank='B', number='16'), 
Classes(rank='B', number='17'), Classes(rank='B', number='18'), Classes(rank='B', number='19'), Classes(rank='B', number='20'), 
Classes(rank='C', number='1'), Classes(rank='C', number='2'), Classes(rank='C', number='3'), Classes(rank='C', number='4'), 
Classes(rank='C', number='5'), Classes(rank='C', number='6'), Classes(rank='C', number='7'), Classes(rank='C', number='8'), 
Classes(rank='C', number='9'), Classes(rank='C', number='10'), Classes(rank='C', number='11'), Classes(rank='C', number='12'), 
Classes(rank='C', number='13'), Classes(rank='C', number='14'), Classes(rank='C', number='15'), Classes(rank='C', number='16'), 
Classes(rank='C', number='17'), Classes(rank='C', number='18'), Classes(rank='C', number='19'), Classes(rank='C', number='20'), 
Classes(rank='D', number='1'), Classes(rank='D', number='2'), Classes(rank='D', number='3'), Classes(rank='D', number='4'), 
Classes(rank='D', number='5'), Classes(rank='D', number='6'), Classes(rank='D', number='7'), Classes(rank='D', number='8'), 
Classes(rank='D', number='9'), Classes(rank='D', number='10'), Classes(rank='D', number='11'), Classes(rank='D', number='12'), 
Classes(rank='D', number='13'), Classes(rank='D', number='14'), Classes(rank='D', number='15'), Classes(rank='D', number='16'), 
Classes(rank='D', number='17'), Classes(rank='D', number='18'), Classes(rank='D', number='19'), Classes(rank='D', number='20')]
"""
profile
Keep Going, Keep Coding!

0๊ฐœ์˜ ๋Œ“๊ธ€