콘텐츠로 건너뛰기

파이썬 Named Tuple 사용 방법

CodeMDD.io

이름 있는 튜플(named tuple)을 사용하여 파이썬 코드를 깔끔하고 파이썬스러운 코드로 작성하기

파이썬의 collections 모듈은 namedtuple()라는 팩토리 함수를 제공합니다. 이 함수는 튜플을 다룰 때 코드를 더욱 파이썬스럽게 작성할 수 있도록 특별히 설계되었습니다. namedtuple()을 사용하면, 값을 명시적인 필드 이름과 도트 표기법(dot notation)을 사용하여 알아볼 수 있는 방식으로 접근할 수 있는 불변한(immutable) 시퀀스 타입을 생성할 수 있습니다. 이는 앞선 어려운 정수 인덱스 대신에 필드 이름을 사용하여 값을 액세스할 수 있습니다.

만약 여러분이 파이썬을 사용하는 경험이 있다면, 파이썬 코딩은 이러한 기능을 사용하여 작성해야 하는 것을 이미 알고 있을 것입니다. 이 튜토리얼에서는 namedtuple을 사용하여 이러한 기술을 더욱 발전시킬 것입니다.

이 튜토리얼에서 다음 사항을 배울 수 있습니다:

  • **namedtuple()**을 사용하여 namedtuple 클래스를 생성하는 방법
  • namedtuple흥미로운 기능을 발견하고 활용하는 방법
  • namedtuple 인스턴스를 사용하여 파이썬스러운 코드를 작성하는 방법
  • namedtuple 또는 유사한 데이터 구조 중 어느 것을 선택해야 하는지 결정하는 방법
  • 새로운 기능을 제공하기 위해 namedtuple서브클래스하는 방법

만약 이러한 기본 개념을 모두 알지 못한다면 걱정하지 마세요! 필요할 때마다 위의 자료들을 참고하면 됩니다.

이름 있는 튜플을 사용하여 파이썬 코드를 깔끔하게 작성하기

파이썬에서 튜플은 다양한 용도로 사용될 수 있습니다. 그러나 튜플은 내부 값에 명확한 의미를 부여하기 어렵습니다. 예를 들어, (22, 7)이라는 튜플에서 이 값은 정확히 무엇을 나타내는 것일까요? 하지만 namedtuple을 사용하면 이러한 문제를 해결할 수 있습니다.

namedtuple을 사용하면 튜플의 각 필드에 의미 있는 이름을 부여할 수 있습니다. 아래의 예제를 살펴보겠습니다:

from collections import namedtuple
# Person namedtuple 선언
Person = namedtuple("Person", ["name", "age"])
# Person namedtuple 인스턴스 생성
person = Person(name="Alice", age=25)
# 필드 이름으로 값 접근
print(person.name)
print(person.age)

위의 코드에서 Person이라는 이름의 namedtuple 클래스를 선언하고, 필드 이름들인 nameage를 정의합니다. 그런 다음 Person 클래스를 사용하여 person이라는 namedtuple 인스턴스를 생성합니다. 이제 person.nameperson.age로 필드 이름을 사용하여 값을 액세스할 수 있습니다.

namedtuple은 불변한(immutable) 시퀀스 타입이므로, 생성 후에 수정할 수 없습니다. 이로 인해 코드를 깔끔하게 유지할 수 있고, 잘못된 변경을 방지할 수 있습니다.

namedtuple()을 사용하여 튜플과 유사한 클래스 생성하기

namedtuple()의 또 다른 유용한 기능은 필수 인자와 선택적 인자를 사용하여 튜플과 유사한 클래스를 생성하는 것입니다.

필수 인자를 namedtuple()에 제공하기

필요한 인자를 namedtuple()에 제공하기 위해, name 인자 뒤에 필드 이름을 순서대로 전달합니다. 이 필드 이름들은 문자열로 제공되어야 합니다. 필드 이름은 공백이나 특수 문자를 포함하면 안되며, 유효한 파이썬 식별자(예: 알파벳, 숫자, 밑줄)여야 합니다.

예를 들어, (1, 2, 3)이라는 튜플을 다음과 같은 필드 이름으로 생성할 수 있습니다:

from collections import namedtuple
# 각 필드에 필드 이름을 제공하여 namedtuple 선언
Triangle = namedtuple("Triangle", ["side1", "side2", "side3"])
# Triangle namedtuple 인스턴스 생성
triangle = Triangle(side1=3, side2=4, side3=5)
# 필드 이름으로 값 접근
print(triangle.side1)
print(triangle.side2)
print(triangle.side3)

위의 코드에서 Triangle이라는 namedtuple을 선언하고 필드 이름들을 side1, side2, side3으로 정의합니다. 그런 다음 Triangle 클래스를 사용하여 triangle이라는 namedtuple 인스턴스를 생성하고, 필드 이름을 사용하여 값을 액세스합니다.

선택적 인자를 namedtuple()과 함께 사용하기

namedtuple()은 선택적 인자도 지원합니다. 선택적 인자를 사용하면 필드 이름에 기본값을 지정할 수 있습니다.

예를 들어, colors라는 tuple에 다음과 같은 필드 이름과 기본값을 사용할 수 있습니다:

from collections import namedtuple
# 빨간색, 초록색, 파란색의 Tuple로 namedtuple 선언
Colors = namedtuple("Colors", ["red", "green", "blue"], defaults=[255, 255, 255])
# Colors namedtuple 인스턴스 생성
colors = Colors(red=125, green=125)
# 필드 이름으로 값 접근
print(colors.red)
print(colors.green)
print(colors.blue)

위의 코드에서 Colors라는 namedtuple을 선언하고 필드 이름들을 red, green, blue으로 정의합니다. defaults 인자를 사용하여 red, green, blue의 기본값을 255로 지정할 수 있습니다. 그런 다음 Colors 클래스를 사용하여 colors라는 namedtuple 인스턴스를 생성하고, 필드 이름을 사용하여 값을 액세스합니다.

이렇게 하면 깔끔한 코드로 쉽게 생성 및 초기화할 수 있습니다.

namedtuple 클래스의 추가 기능 살펴보기

namedtuple 클래스에는 튜플과 유사한 필드 기반 구조를 감싸는 데 도움이 되는 몇 가지 추가 기능이 있습니다.

namedtuple 인스턴스를 반복 가능한 객체에서 생성하기

namedtuple 인스턴스는 반복 가능한 객체에서 생성될 수 있습니다. 이를 통해 다른 시퀀스 타입에서 namedtuple 인스턴스를 생성할 수 있습니다.

예를 들어, 다음과 같은 튜플 리스트가 있는 경우:

values = [("Alice", 25), ("Bob", 30), ("Charlie", 35)]

이 리스트에서 namedtuple 인스턴스를 생성할 수 있습니다:

from collections import namedtuple
# Person namedtuple 선언
Person = namedtuple("Person", ["name", "age"])
# values 리스트에서 Person namedtuple 인스턴스들 생성
people = [Person(*value) for value in values]
# 필드 이름으로 값 접근
for person in people:
print(person.name, person.age)

위의 코드에서, values라는 리스트에서 namedtuple 인스턴스를 생성하기 위해 리스트 컴프리헨션(혹은 반복문)을 사용합니다. *value는 튜플의 각 값을 Person 클래스 생성자에 전달하여 인스턴스를 생성하는 데 사용됩니다. 그런 다음 필드 이름을 사용하여 값에 접근할 수 있습니다.

namedtuple 인스턴스를 딕셔너리로 변환하기

namedtuple 인스턴스는 필드 이름과 값을 매핑하는 딕셔너리로 변환될 수 있습니다. 이는 필드 이름을 기반으로 튜플의 데이터를 쉽게 처리하고 조작할 수 있는 방법을 제공합니다.

예를 들어, 다음과 같은 namedtuple 인스턴스가 있다고 가정해 봅시다:

from collections import namedtuple
# Person namedtuple 인스턴스 생성
person = Person(name="Alice", age=25)

이 경우 .asdict() 메서드를 사용하여 Person 인스턴스를 딕셔너리로 변환할 수 있습니다:

# .asdict()를 사용하여 딕셔너리로 변환
person_dict = person._asdict()
# 딕셔너리 출력
print(person_dict)

위의 코드에서, person이라는 namedtuple 인스턴스를 .asdict() 메서드를 사용하여 딕셔너리로 변환합니다. _asdict() 메서드는 인스턴스의 필드 이름과 값을 매핑하는 딕셔너리를 반환합니다. 그런 다음 딕셔너리를 출력합니다.

기존의 namedtuple 인스턴스에서 필드를 교체하기

namedtuple은 불변한(immutable) 시퀀스 타입이기 때문에 생성 후에 필드 값을 수정할 수 없습니다. 그러나 namedtuple 인스턴스의 일부 또는 모든 필드를 교체할 수 있는 방법이 있습니다. 이를 통해 새로운 namedtuple 인스턴스를 생성하고 기존 인스턴스를 변경할 수 있습니다.

이를 수행하는 방법은 다음과 같습니다:

# 기존 namedtuple 인스턴스 생성
person = Person(name="Alice", age=25)
# 필드를 교체하여 새로운 namedtuple 인스턴스 생성
new_person = person._replace(age=30)
# 필드 이름으로 값 접근
print(new_person.name)
print(new_person.age)

위의 코드에서, 먼저 Person 클래스를 사용하여 person이라는 namedtuple 인스턴스를 생성합니다. 그런 다음 .replace() 메서드를 사용하여 new_person이라는 새로운 namedtuple 인스턴스를 생성하고, 필드 값을 변경합니다. 변경한 필드를 제외한 나머지 필드는 이전의 person 인스턴스와 동일하게 유지됩니다. 마지막으로 필드 이름을 사용하여 새로운 namedtuple 인스턴스에 접근할 수 있습니다.

이를 통해 namedtuple 인스턴스에 대한 변경이 있는 경우 기존 인스턴스를 수정하지 않고도 새로운 인스턴스를 만들 수 있습니다.

추가적인 namedtuple 속성 탐색하기

namedtuple에는 추가적인 속성들이 있습니다. 이러한 속성들을 이용하면 namedtuple을 더 유연하게 사용할 수 있습니다.

다음은 몇 가지 예시입니다:

  • _fields: 튜플의 필드 이름을 제공합니다.
  • _make(iterable): 반복 가능한(iterable) 객체에서 namedtuple 인스턴스를 생성합니다.
  • _asdict(): namedtuple 인스턴스를 필드 이름과 값으로 매핑하는 딕셔너리로 변환합니다.

예를 들어, _fields 속성을 사용하여 namedtuple 클래스의 모든 필드 이름을 출력할 수 있습니다:

# Person namedtuple의 필드 이름 가져오기
fields = Person._fields
# 필드 이름 출력
for field in fields:
print(field)

위의 코드에서, Person 클래스의 _fields 속성을 사용하여 namedtuple 클래스의 필드 이름을 가져옵니다. 그런 다음 이를 반복문을 사용하여 출력합니다.

각 속성의 자세한 내용은 파이썬 공식 문서를 참고하시기 바랍니다.

namedtuple을 사용한 파이썬스러운 코드 작성하기

이제 namedtuple이 어떤 것인지, 어떻게 사용하는지, 어떤 장점을 제공하는지 알았으므로, 이제는 namedtuple을 사용하여 파이썬스러운 코드를 작성하는 방법을 알아보겠습니다.

인덱스 대신 필드 이름 사용하기

namedtuple을 사용하여 코드를 작성하면 인덱스 대신 필드 이름을 사용하여 값을 읽고 쓸 수 있습니다. 이를 통해 코드를 더 가독성 있게 만들 수 있습니다.

예를 들어, 다음과 같은 namedtuple을 사용하는 경우:

# 예시 namedtuple 클래스
Person = namedtuple("Person", ["name", "age", "gender"])

이름이 Alice인 사람의 정보를 튜플에서 얻는다고 가정해 봅시다:

# 사람의 정보를 얻는 코드
person = ("Alice", 25, "female")
name = person[0]
age = person[1]
gender = person[2]
print(name, age, gender)

이 코드는 인덱스를 사용하여 값을 읽고 있기 때문에 가독성이 떨어집니다. 그러나 namedtuple을 사용하여 코드를 다시 작성하면 다음과 같이 됩니다:

# 사람의 정보를 얻는 코드
person = Person(name="Alice", age=25, gender="female")
name = person.name
age = person.age
gender = person.gender
print(name, age, gender)

이 코드는 이름 있는 필드를 사용하여 값을 읽으므로 인덱스에 대한 의존성이 없어집니다. 이로 인해 코드의 가독성이 향상됩니다.

여러 개의 명명된 값을 함수에서 반환하기

namedtuple을 사용하면 함수에서 여러 개의 명명된 값을 반환할 수 있습니다. 이는 코드를 더욱 명확하고 이해하기 쉽게 만듭니다.

예를 들어, namedtuple을 사용하지 않은 경우 다음과 같은 함수가 있다고 가정해 봅시다:

# 여러 개의 값을 반환하는 함수
def get_person_info():
name = "Alice"
age = 25
gender = "female"
return name, age, gender
# 여러 개의 값을 반환받음
person_info = get_person_info()
name = person_info[0]
age = person_info[1]
gender = person_info[2]
print(name, age, gender)

이 코드는 여러 개의 값을 반환하는 방법으로 튜플을 사용하고 있습니다. 그러나 namedtuple을 사용하여 코드를 다시 작성하면 다음과 같이 됩니다:

# 여러 개의 값을 반환하는 함수
def get_person_info():
Person = namedtuple("Person", ["name", "age", "gender"])
return Person(name="Alice", age=25, gender="female")
# 한 개의 namedtuple 인스턴스를 반환받음
person_info = get_person_info()
name = person_info.name
age = person_info.age
gender = person_info.gender
print(name, age, gender)

이 코드는 명명된 필드를 사용하여 인덱스에 대한 의존성을 제거하고 가독성을 향상시킵니다.

함수의 인수 수를 줄이기

namedtuple을 사용하면 함수의 인수 수를 줄일 수 있습니다. 이는 코드 작성과 유지보수를 더욱 쉽게 만듭니다.

예를 들어, 다음과 같은 함수가 있습니다:

# 많은 인수를 갖는 함수
def calculate_area(length, width, height):
return length * width * height

이 함수는 길이(length), 너비(width), 높이(height)와 같은 다양한 인수를 사용합니다. 그러나 namedtuple을 사용하여 코드를 작성하면 다음과 같이 됩니다:

from collections import namedtuple
# 3D Rectangle namedtuple 선언
Rectangle3D = namedtuple("Rectangle3D", ["length", "width", "height"])
# namedtuple 인스턴스를 인수로 받는 함수
def calculate_area(rectangle):
return rectangle.length * rectangle.width * rectangle.height
# namedtuple 인스턴스를 생성하여 함수 호출
dimensions = Rectangle3D(length=10, width=5, height=3)
area = calculate_area(dimensions)
print(area)

이 코드는 Rectangle3D라는 namedtuple을 선언하고 필드 이름들을 length, width, height으로 정의합니다. 그런 다음 calculate_area 함수는 Rectangle3D namedtuple 인스턴스를 인수로 받아 계산을 수행합니다. 인수의 의미를 명시적으로 전달함으로써 함수의 가독성과 유지보수성을 향상시킬 수 있습니다.

파일 및 데이터베이스로부터 탭 형식의 데이터 읽어오기

namedtuple을 사용하면 파일이나 데이터베이스로부터 탭 형식의 데이터를 읽어올 수 있습니다. 이는 데이터를 구조화하여 처리하는 데 도움이 됩니다.

예를 들어, 다음과 같은 탭 구분자로 분리된 데이터 파일이 있다고 가정해 봅시다:

John Smith
Alice Johnson
Bob Brown

이러한 데이터를 처리하기 위해 다음과 같은 namedtuple을 사용한 함수를 만들 수 있습니다:

from collections import namedtuple
# Person namedtuple 선언
Person = namedtuple("Person", ["first_name", "last_name"])
# 파일에서 데이터 읽어오기
def read_data(filename):
data = []
with open(filename, "r") as file:
for line in file:
fields = line.strip().split("\t")
person = Person(fields[0], fields[1])
data.append(person)
return data
# 데이터 파일로부터 데이터 읽어오기
people = read_data("data.txt")
# 데이터 출력
for person in people:
print(person.first_name, person.last_name)

위의 코드에서, Person이라는 namedtuple을 선언하고 필드 이름들을 first_name, last_name으로 정의합니다. 그런 다음 read_data 함수를 작성하여 파일에서 데이터를 읽고 Person namedtuple 인스턴스를 생성합니다. 각 namedtuple 인스턴스는 데이터를 구조화하여 처리하는 데 사용됩니다. 최종적으로 데이터를 출력합니다.

이렇게 하면 탭 형식의 데이터 파일을 깔끔하게 처리하고, 데이터를 쉽게 액세스할 수 있는 구조로 변경할 수 있습니다.

namedtuple vs 다른 데이터 구조들

namedtuple은 다른 데이터 구조들과 비교해서 어떤 장단점을 가지고 있을까요? 우리는 다음과 같은 몇 가지 데이터 구조들과 비교해 볼 수 있습니다:

namedtuple vs 딕셔너리

namedtuple과 딕셔너리는 모두 일련의 키와 값으로 구성됩니다. 그러나 namedtuple은 구조화된 데이터를 저장하고 접근하기 위해 사용되는 불변한(immutable) 시퀀스 타입입니다. 반면에, 딕셔너리는 유동적인 키-값 쌍의 집합이며, 중첩된 데이터 구조를 처리하는 데 적합합니다.

딕셔너리를 사용할 때에는 키를 사용하여 필드에 액세스할 수 있기 때문에 가독성이 높을 수 있습니다. 그러나 namedtuple은 필드 이름을 사용하여 액세스할 수 있으므로 인덱스 대신 의미 있는 이름을 사용하여 값을 읽고 쓸 수 있습니다. 이는 가독성을 향상시키고 코드를 더 명확하게 만듭니다.

딕셔너리보다 namedtuple의 특정 장점은 더욱 정적인 구조를 제공한다는 것입니다. 필드 이름이 이미 선언되어 있기 때문에 필드를 표현하는 데 필요한 잠재적인 동적 타입 확인을 피할 수 있습니다.

딕셔너리는 유동적인 데이터를 다루는 데에 더 적합하며, namedtuple은 구조화된 데이터를 다루는 데에 더 적합합니다.

namedtuple vs 데이터 클래스

데이터 클래스(data class)는 namedtuple과 매우 유사한 구조를 가지고 있습니다. 데이터 클래스는 파이썬 3.7 이상에서 사용할 수 있는 표준 라이브러리인 dataclasses 모듈로 제공됩니다.

데이터 클래스도 키워드를 사용하여 필드를 선언할 수 있습니다. 그러나 데이터 클래스는 namedtuple에 비해 더욱 고급 기능을 제공합니다. 예를 들어, 데이터 클래스는 초기값, 타입 힌트, 메서드, 상속 등의 기능을 추가적으로 제공할 수 있습니다. 또한 데이터 클래스는 필드 값을 변경할 수 있는 가변(mutable) 시퀀스 타입으로 사용됩니다.

따라서, namedtuple은 간단하고 구조화된 데이터를 다루는 데 사용되는 반면, 데이터 클래스는 더 복잡하고 동적인 데이터를 다루는 데 사용됩니다.

namedtuple vs typing.NamedTuple

typing.NamedTuplenamedtuple과 비슷한 기능을 갖춘 클래스이지만, 파이썬 3.6 이상에서 사용할 수 있는 표준 라이브러리인 typing 모듈에서 제공됩니다.

typing.NamedTupletyping 모듈이 제공하는 타입 힌트와 함께 사용될 수 있습니다. 이를 통해 필드의 타입을 명시할 수 있으며, 가독성을 향상시킬 수 있습니다.

typing.NamedTuplenamedtuple과 비슷한 목적을 가지고 있으며, 코드를 더 명확하고 이해하기 쉽게 만드는 데 도움이 됩니다.

namedtuple 클래스 서브클래싱하기

namedtuple 클래스도 상속을 할 수 있습니다. 이를 통해 namedtuple에 새로운 기능을 추가하여 그 자체로 사용할 수 있는 새로운 클래스를 생성할 수 있습니다.

예를 들어, namedtuple을 사용하여 생성한 클래스에 추가 메서드를 포함시킬 수 있습니다:

from collections import namedtuple
# Person namedtuple 선언
Person = namedtuple("Person", ["name", "age"])
# Additional features을 포함하는 Person 클래스 생성
class PersonWithAdditionalFeatures(Person):
def get_initial(self):
initial = self.name[0].upper()
return f"{initial}."
# PersonWithAdditionalFeatures 인스턴스 생성
person = PersonWithAdditionalFeatures(name="Alice", age=25)
# 추가적인 기능 사용
initial = person.get_initial()
print(initial)

위의 코드에서, Person이라는 namedtuple을 선언하고 필드 이름들을 name, age로 정의합니다. 그런 다음 PersonWithAdditionalFeatures 클래스를 생성하여 Person을 상속합니다. 이 클래스는 Person의 모든 기능을 포함하며, get_initial이라는 메서드를 추가로 가지고 있습니다. 이 메서드는 인스턴스의 이름 문자열의 첫 글자를 대문자로 변환한 뒤, 마침표와 함께 문자열을 반환합니다.

이렇게 함으로써 namedtuple 클래스를 상속하여 원하는 기능을 추가할 수 있습니다. 이를 통해 namedtuple이 제공하는 이점과 더불어 새로운 기능을 활용할 수 있습니다.

튜플 vs namedtuple의 생성 시간 측정하기

튜플과 namedtuple은 모두 시퀀스 타입으로 사용할 수 있습니다. 이 두 가지 타입의 성능을 비교하기 위해 생성 시간을 측정해 보겠습니다.

import timeit
from collections import namedtuple
# 일반 튜플을 사용하여 생성 시간 측정
tuple_creation_time = timeit.timeit("tuple((1, 2, 3))", setup="from __main__ import tuple", number=1000000)
# namedtupel을 사용하여 생성 시간 측정
namedtuple_creation_time = timeit.timeit("Point(1, 2, 3)", setup="from __main__ import Point", number=1000000)
print("Tuple creation time:", tuple_creation_time)
print("Namedtuple creation time:", namedtuple_creation_time)

위의 코드에서, timeit 모듈을 사용하여 튜플과 namedtuple의 생성 시간을 측정합니다. timeit.timeit() 함수는 실행할 코드와 함께 실행할 횟수를 제공합니다.

이렇게하면 튜플과 namedtuple의 생성 시간을 비교할 수 있으며, 성능 차이를 확인할 수 있습니다.

결론

이제 namedtuple을 사용하여 파이썬스러운 코드를 작성하는 방법을 배웠습니다. namedtuple을 사용하면 구조화된 데이터를 보다 명확하고 가독성 있게 다룰 수 있습니다. namedtuple은 필드 기반의 튜플을 생성하는 데 도움이 되며, 필드 이름을 사용하여 값을 접근하고 수정할 수 있습니다. 또한 namedtuple은 반복 가능한 객체에서 인스턴스를 생성하거나 딕셔너리로 변환하는 등의 추가 기능을 제공합니다.

그림까지 포함 된이 자습서를 통해 파이썬 튜토리얼을 제공했습니다. 이 자습서에는 파이썬에 대한 이해와 함께 몇 가지 예제가 포함되어 있습니다. 파이썬의 공식 문서와 함께 이 자습서를 사용하여 namedtuple을 사용하여 깔끔하고 효율적인 코드를 작성할 수 있도록 실습해보세요.