튜플

튜플 에서 Python

15개의 연습 문제

튜플 소개

튜플은 항목을 _순서_대로 담는 불변 컬렉션이에요.

대부분의 컬렉션(내장 타입인 list, dict, set를 참고해요)과 마찬가지로, tuples에는 여러 데이터 타입을 담을 수 있어요. 다른 tuples도 포함해서요. 튜플의 원소는 for item in <tuple> 구문으로 반복할 수 있어요. 원소의 인덱스와 값이 모두 필요하면 for index, item in enumerate(<tuple>)를 사용할 수 있어요.

다른 시퀀스와 마찬가지로, tuples 안의 원소는 왼쪽에서부터는 0-based index, 오른쪽에서부터는 -1-based index 번호를 사용하는 _대괄호 표기법_으로 접근할 수 있어요. 튜플은 _슬라이스 표기법_이나 <tuple>.copy()로 전체 또는 일부를 복사할 수 있고, 모든 일반 시퀀스 연산을 지원해요. _불변_이기 때문에 tuples는 가변 시퀀스 연산을 지원하지 않아요.

튜플은 다른 컬렉션 타입에 비해 메모리 공간을 아주 적게 차지하고, 인덱스로 접근할 때 상수 시간(O(1))이 걸려요. 하지만 한번 만들어지면 크기를 바꾸거나 정렬하거나 수정할 수 없어서, 데이터를 자주 변경하거나 갱신해야 할 때는 유연성이 떨어져요. 잦은 갱신이나 확장이 필요하다면 list, collections.deque, array.array가 더 나은 자료 구조일 수 있어요.


튜플 생성

튜플은 여러 방법으로 만들 수 있어요. tuple 클래스 생성자를 쓰거나 (<element_1>, <element_2>) (tuple 리터럴) 선언을 사용해요.

tuple() 생성자를 비워 두거나 _이터러블_과 함께 사용하기:

>>> no_elements = tuple()
()

# The constructor *requires* an iterable, so single elements must be passed in a list or another tuple.
>>> one_element = tuple([16])
(16,)

문자열은 이터러블이기 때문에, tuple() 생성자에 str 하나를 인자로 넘기면 의외의 결과가 나올 수 있어요:

# String elements (characters) are iterated through and added to the tuple
>>> multiple_elements_string = tuple("Timbuktu")
('T', 'i', 'm', 'b', 'u', 'k', 't', 'u')

다른 이터러블도 원소가 하나씩 추가돼요:

>>> multiple_elements_list = tuple(["Parrot", "Bird", 334782])
("Parrot", "Bird", 334782)

>>> multiple_elements_set = tuple({2, 3, 5, 7, 11})
(2,3,5,7,11)

dict를 반복하면 기본적으로 키를 순회해요. 딕셔너리로 만든 튜플에 키와 값은 모두 담고 싶다면 <dict>.items()를 사용해요. 그러면 (key, value) tuples의 이터레이터가 반환돼요.

>>> source_data = {"fish": "gold", "monkey": "brown"}

>>> multiple_elements_dict_1 = tuple(source_data)
('fish', 'monkey')

>>> multiple_elements_dict_2 = tuple(source_data.items())
(('fish', 'gold'), ('monkey', 'brown'))
_리터럴_로 튜플 선언하기:

tuple() 생성자는 이터러블(또는 아무것도)만 인자로 받기 때문에, 리터럴 방식으로 원소가 하나인 튜플을 만드는 것이 훨씬 쉬워요.

>>> no_elements = ()
()

>>> one_element = ("Guava",)
("Guava",)

일반적으로 tuple 리터럴을 만들 때 괄호는 필요하지 않고, 쉼표만 있으면 돼요. 하지만 대부분의 상황에서는 (<element_1>, <element_2>) 형태가 더 읽기 좋다고 여겨져요. 빈 튜플이나 원소가 하나인 튜플처럼 모호한 경우, 또는 함수가 튜플을 인자로 받는 경우에는 괄호가 필요해요.

>>> elements_separated_with_commas = "Parrot", "Bird", 334782
("Parrot", "Bird", 334782)

>>> elements_with_commas_and_parentheses = ("Triangle", 60, 60, 60)
("Triangle", 60, 60, 60)

다른 tuples를 포함해, 다른 자료 구조도 tuple의 원소로 넣을 수 있어요.

>>> nested_data_structures = ({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))
({"fish": "gold", "monkey": "brown", "parrot" : "grey"}, ("fish", "mammal", "bird"))

>>> nested_data_structures_1 = (["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))
(["fish", "gold", "monkey", "brown", "parrot", "grey"], ("fish", "mammal", "bird"))

튜플은 더하기 + 연산자로 이어 붙일 수 있어요. 이때 각 tuple이 풀리고, 합쳐진 새로운 tuple이 만들어져요.

>>> new_via_concatenate = ("George", 5) + ("cat", "Tabby")
("George", 5, "cat", "Tabby")

#likewise, using the multiplication operator * is the equivalent of using + n times
>>> first_group = ("cat", "dog", "elephant")

>>> multiplied_group = first_group * 3
('cat', 'dog', 'elephant', 'cat', 'dog', 'elephant', 'cat', 'dog', 'elephant')

데이터 접근하기

튜플 안의 원소는 (다른 시퀀스 타입인 str, list처럼) 대괄호 표기법_으로 접근할 수 있어요. 인덱스는 left --> right (0부터 시작) 또는 right --> left (-1부터 시작_) 방향으로 셀 수 있어요. 튜플은 _슬라이스 표기법_이나 <tuple>.copy()를 사용해 전체 또는 일부를 복사할 수도 있어요.

>>> student_info = ("Alyssa", "grade 3", "female", 8)

#name is at index 0 or index -4
>>> student_name = student_info[0]
Alyssa

>>> student_name = student_info[-4]
Alyssa

#age is at index 3 or index -1
>>> student_age_1 = student_info[3]
8

>>> student_age_2 = student_info[-1]
8

원소 반복하기

튜플 안의 원소는 for item in <tuple> 구문으로 루프를 돌며 _반복_할 수 있어요. 인덱스와 값이 모두 필요하면 for index, item in enumerate(<tuple>)를 사용할 수 있어요.

>>> student_info = ("Alyssa", "grade 3", "female", 8)
>>> for item in student_info:
...   print(item)
...
Alyssa
grade 3
female
8

>>> for index, item in enumerate(student_info):
...  print("Index is: " + str(index) + ", value is: " + str(item) + ".")
...
Index is: 0, value is: Alyssa.
Index is: 1, value is: grade 3.
Index is: 2, value is: female.
Index is: 3, value is: 8.

동질적인 정보로서의 튜플

튜플은 조직상 또는 개념상 동질적인 데이터를 담아 하나의 정보 단위로 다루는 _레코드_로 자주 사용돼요. 개별 원소의 데이터 타입이 서로 다르더라도 말이에요.

>>> student_info = ("Alyssa", "grade 3", "female", 8)

튜플은 동질적이고 불변인 데이터 시퀀스가 필요할 때도 사용해요. 예를 들어 hashability를 만족해야 하거나, set에 저장하거나, 딕셔너리의 키를 만들 때처럼요.

tuples는 대부분의 경우 _불변_이지만, 어떤 자료 구조나 객체든 담을 수 있기 때문에 원소 중 하나라도 _가변 타입_이면 _가변_이 될 수 있다는 점에 주의해요. tuple 안에 가변 데이터 타입을 넣으면 그 tuple은 해시할 수 없게 돼요.

>>> cmyk_color_map = {
        (.69, .3, .48, .1) : ("Teal 700", (59, 178, 146), 0x3BB292),
        (0, .5, 1, 0) : ("Pantone 151", (247, 127, 1), 0xF77F01),
        (.37, .89, 0, .44) : ("Pantone 267", (89, 16, 142), 0x59108E),
        (0, 1, .46, .45) : ("Pantone 228", (140, 0, 76), 0x8C004C)
    }

>>> unique_rgb_colors = {
        (59, 178, 146),
        (247, 127, 1),
        (89, 16, 142),
        (140, 0, 76),
        (76, 0, 140)
     }

>>> teal_700 = hash((59, 178, 146))

>>> teal_700 = hash(("Pantone 228", [(140, 0, 76), 0x8C004C]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

확장 튜플과 관련 데이터 타입

튜플은 _레코드_로 자주 사용되지만, 그 안의 데이터는 위치/_인덱스_로만 접근할 수 있어요. collections 모듈의 namedtuple() 클래스는 기본 튜플 기능을 확장해 원소를 _이름_으로 접근할 수 있게 해줘요. 또한 dataclass를 활용하면 비슷하게 이름이 붙은 속성 기능을 제공할 수 있어요. 다만 장단점이 있어요.

GitHub에서 편집 링크가 새 창이나 탭에서 열려요

튜플 배우기

연습이 잠겨 있어요

튜플 개념을 연습하려면 연습 문제 5개를 더 잠금 해제해요