<개인공부>/[Python]

[python] 파이썬 튜플(tuple)에 대해서

BlockDMask 2020. 12. 6. 00:30
반응형

안녕하세요. BlockDMask 입니다.
오늘은 파이썬의 자료형중 하나인 튜플 (tuple)에 대해서 알아보려고 합니다.
지난시간에 배운 리스트와 사용법은 비슷하지만 차이가 존재합니다. 리스트를 보고 오신 분이라면, 비교해보면서 학습하는것도 좋은 방법인것 같네요.

<목차>
1. 튜플(tuple)이란? 튜플의 특징
2. 튜플(tuple) 가지고 놀기1 (인덱싱, 슬라이싱, len, 더하기, 곱하기, in, count)
3. 튜플(tuple) 가지고 놀기2 (튜플에 의한 반환, for예제, 중첩, 괄호 생략, 튜플 스왑, 튜플로 변환)


1. 파이썬 tuple이란?


"튜플이란 셀수 있는 수량의 순서있는 열거이다" 라고 위키 백과에 나와있네요.

튜플의 모양은 아래와 같습니다.
t1 = ()
t2 = (5, )
t3 = (5, 6, 4, 5)

이런식으로 튜플을 만들 수 있습니다.
리스트에서는 대괄호 "[, ]"를 이용해서 리스트를 만들었다면
튜플에서는 소괄호 "(, )"를 이용해서 튜플을 만들 수 있습니다.

비어있는 튜플을 만들려면 t1 = () 처럼 비어있는 소괄호를 넣으면 됩니다.

눈치가 빠르신 분들은 이미 눈치를 채셨겠지만,
값이 1개만 들어있는 튜플을 만들때에는 t2 = (1, ) 처럼 값을 하나 넣고 콤마(,)를 넣어주어야 합니다. 튜플의 규칙이죠.

또 튜플은 set자료형이랑 달리 중복된 값을 넣을 수 있습니다. t3을 보면 5가 두번 있는것을 볼 수 있죠. 튜플은 내부의 값이 중복되도 상관없습니다.


튜플의 특징

튜플에서 가장 중요한 특징은 "값이 변하지 않는다" 라는 특징인데요.
리스트에서는 값을 변경할수 있지만, 튜플은 내부의 값을 변경하거나 삭제 할 수 없습니다.

1
2
3
4
5
6
7
8
= ('b''l''o''g'98)
 
# 요소 값 변경 불가능 ERROR 
# a[0] = 10 
 
# 요소 값 삭제 불가능 ERROR
# del a[0]
 
cs

a[0] = 10 을 이용해서 요소 값을 변경하려 하면 에러가 발생하고
del a[0] 을 이용해서 요소의 값을 삭제하려 해도 에러가 발생합니다.

이렇게, 튜플의 내부 값은 한번 정하면 변하지 않습니다.

아 물론 튜플 자체는 삭제 가능합니다. 튜플전체 삭제 del a 이건 가능입니다.


위에서 배운 튜플의 특징에 대해서 요약 정리를 해보면 아래와 같습니다.
특징1) 소괄호 이용해서 생성 "(, )"
특징2) 비어있는 튜플은 ()
특징3) 값이 하나만 있는 튜플은 (5, ) 콤마 하나 꼭 붙여야함
특징4) 값이 중복될 수 있다.
특징5) 튜플의 요소 값은 변경하거나 삭제할 수 없다.


2. 파이썬 tuple 예제1
(인덱싱, 슬라이싱, 길이, 더하기, 곱하기, in, 갯수 세기)


2-1) 튜플 인덱싱

인덱싱이란 값에 접근을 하는 방법입니다.
튜플[index]의 방법으로 값에 접근할 수 있습니다. 바로 예제로 확인해볼까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
t1 = ('a''b''c'1098)
 
print(f't1[0] : {t1[0]}')
print(f't1[1] : {t1[1]}')
print(f't1[2] : {t1[2]}')
print(f't1[3] : {t1[3]}')
print(f't1[4] : {t1[4]}')
print(f't1[5] : {t1[5]}')
# print(t1[6]) 범위를 넘어가므로 error
print(f't1[-1] : {t1[-1]}')
print(f't1[-2] : {t1[-2]}')
print(f't1[-3] : {t1[-3]}')
print(f't1[-4] : {t1[-4]}')
print(f't1[-5] : {t1[-5]}')
print(f't1[-6] : {t1[-6]}')
# print(t1[-7]) 범위를 넘어가므로 error
 
cs

이런식으로 t1[index]를 이용해서 튜플의 값에 접근을 할수 있습니다.
내부에 index에는 원하는 곳의 인덱스 값을 집어 넣으면되는데 인덱스는 0부터 시작합니다. 예제에 보이듯이 마이너스 인덱스도 가능합니다. 


2-2) 튜플 슬라이싱

슬라이싱은 튜플을 일정 부분 잘라서 새로운 튜플을 만들어 내는것을 말합니다.
원본 튜플 a가 있다면 a[앞index : 뒤index] 의 형태로 입력을 하여 

앞index 에서 부터 뒤index -1 까지의 범위의 요소값을 새로운 튜플로 만들어서 반환해 줍니다.
튜플[0:2] 라고 하면 튜플[0]과 튜플[1]의 요소값을 묶어서 튜플로 만들어 반환해줍니다. 즉 요소0, 요소1을 새로운 튜플로 잘라낸다. 하여서 슬라이싱이라 합니다.
예제로 볼까요?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
= ('b''l''o''c'1011)
= a[0:2]
= a[0:-2]
= a[:]
= a[4:]
= a[:4]
 
print(f'a       : {a}')
print(f'a[0:2]  : {b}')
print(f'a[0:-2] : {c}')
print(f'a[:]    : {d}')
print(f'a[4:]   : {e}')
print(f'a[:4]   : {f}')
 
cs

이렇게 튜플을 슬라이싱 할 수 있습니다.
예제에서 보듯이 앞index에서 뒤index -1 까지 범위의 요소를 자르는걸 알 수 있습니다.
앞index, 뒤index가 비어있는걸 볼 수 있는데, 이것은 끝까지 라는 뜻입니다.
[:] 앞뒤 끝까지.
[앞index: ] 앞index 부터 요소 끝까지.
[ : 뒤index] 맨 앞부터 뒤index - 1까지 입니다.


2-3) 튜플 길이 구하기

길이를 구하는건 파이썬 내장함수인 len 함수를 이용하면 됩니다.

1
2
3
4
5
6
7
8
9
10
= (12345)
= ()
= (4,)
= ('b''l''o''c''k')
 
print(f'len(a) : {len(a)}')
print(f'len(b) : {len(b)}')
print(f'len(c) : {len(c)}')
print(f'len(d) : {len(d)}')
 
cs

len(튜플)을 이용하면 튜플의 길이를 구할 수 있습니다.


2-4) 튜플 더하기

튜플은 튜플끼리 더할수 있는데요. 그러면 연결된 또하나의 튜플이됩니다.
바로 예제로 확인하시죠.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
= (12345)
= ()
= (4,)
= ('1''2'34'k')
 
result1 = a + b
result2 = a + c
result3 = a + d
result4 = a + b + c + d
 
 
print(f'a + b = {result1}')
print(f'a + c = {result2}')
print(f'a + d = {result3}')
print(f'a + b + c + d = {result4}')
 
cs

이렇게 튜플끼리 더하게 되면 연결된 또다른 튜플이 생성됩니다.


2-5) 튜플 곱하기

튜플을 곱하게 되면 튜플은 해당 횟수만큼 반복된 튜플을 만들어 줍니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
t1 = (12)
t2 = ()
t3 = (10,)
t4 = ('a''b''c')
 
result1 = t1 * 2
result2 = t2 * 4
result3 = t3 * 10
result4 = t4 * 3
 
 
print(f't1 * 2 = {result1}')
print(f't2 * 4 = {result2}')
print(f't3 * 10 = {result3}')
print(f't4 * 3 = {result4}')
 
cs

이런식으로 해당 튜플 전체가 곱해진 n 만큼 반복되어 또다른 튜플을 만들어 줍니다.
당연하게도 비어있는 튜플 () 은 몇을 곱해도 비어있는 () 튜플을 만들어 줍니다.


2-6) 튜플 내부에 값이 있는지 확인하기 (in)

튜플 내부에 특정한 값이 있는지 확인하기 위해서는 in 을 사용합니다.
if문과 한번 같이 사용해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
t1 = (12)
t2 = ()
t3 = ('b''l''o''c''k')
 
if 1 in t1:
    print('1 in t1 is true')
else:
    print('1 in t1 is not true')
 
 
if 1 in t2:
    print('1 in t2 is true')
else:
    print('1 in t2 is not true')
 
 
if 'z' in t3:
    print('"z" in t3 is true')
else:
    print('"z" in t3 is not true')
 
cs

이런식으로 in 을 이용해서 튜플 내부에 확인하고 싶은 값이 있는지 확인 할 수 있습니다.


2-7) 튜플 내부에 값이 몇개 있는지 확인하기 (count)

count(k) 함수를 이용하여 튜플 내부에 해당 값이 몇개가 있는지 확인 할 수 있습니다.
count(k) 함수는 대소문자를 구분합니다.

1
2
3
4
5
6
7
8
= (1357911)
= ('B''l''o''c''k''D''M''a''s''k')
 
print(f'a.count(5) = {a.count(5)}')
print(f'a.count(0) = {a.count(0)}')
print(f'b.count("b") = {b.count("b")}')
print(f'b.count("k") = {b.count("k")}')
 
cs

튜플 b에서 대문자 'B'는 존재하지만 소문자 'b'는 존재하지 않기 때문에 0이 나오는걸 알 수 있습니다. 여기서 count 함수가 대소문자를 구분한다는 것을 알 수 있습니다.


3. 파이썬 tuple 예제2
(괄호 생략, 튜플 반환, 스왑, 반복문 for, 중첩, 튜플로 타입 변환)


3-1) tuple 괄호 생략

튜플을 생성할때 혹은 튜플을 다룰때 () 소괄호는 사실 필수 조건은 아닙니다. 즉, 생략이 가능합니다.

그래서 튜플을 생성할때 t1 = 1, 2, 3, 4, 5 라 하면 파이썬은 이것을 튜플이라 여기게 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
= 345
= 7,
= 'o''p''q'
 
 
print(f'type(a) : {type(a)}')
print(f'type(b) : {type(b)}')
print(f'type(c) : {type(c)}')
 
print(f'a : {a}')
print(f'b : {b}')
print(f'c : {c}')
 
cs

이렇게 소괄호가 없어도 튜플로 만들어 집니다.
이러한 특징을 이용해서 우리는 많은것을 할 수 있습니다.


3-2) 튜플 타입의 반환

소괄호가 없다? 소괄호가 없어도 튜플이라니 참으로 신기하죠?
우리는 이 특징을 이용해서 마치 함수에서 여러개(?)를 반환하는 것 처럼 할 수 있습니다.
바로 예제로 보시죠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 튜플 반환
def get_info(num, name, phone):
    return num, name, phone
 
 
= '1'
= 'kim'
= 'apple'
 
 
# 하나의 변수에 받음
result1 = get_info(a, b, c)
print(f'type(result1) = {type(result1)}')
print(f'result1 = {result1}')
 
 
# 일일히 하나씩 받음
d, e, f = get_info(a, b, c)
print(d)
print(e)
print(f)
 
cs

예제에서 보시듯 함수의 반환이 return num, name, phone 이렇게 마치 세개를 반환하는 것 처럼 보입니다.

이는 (num, name, phone)이라는 튜플 자료형 하나를 반환하는것과 동일하게 여겨집니다. 그렇기 때문에 result1인 하나의 변수로 받게 되면 그 변수는 튜플 타입으로 받아집니다. 이해가 되시나요?

이렇게 result1 처럼 하나의 튜플 타입으로 받는 것도 가능하지만, 튜플의 unpack 기능이 있기 때문에 하나하나 나눠서 받을 수 도 있습니다. d, e, f 처럼요.


3-3) tuple로 인한 스왑

바로 위 예제에서 보았듯이 튜플에는 unpack 기능 (하나하나 나눠주는)과 다시 합쳐주는 pack 기능이 있기 때문에 우리는 변수의 스왑을 매우 편리하게 할 수 있습니다.

바로 예제로 확인하시죠.

1
2
3
4
5
6
# a1, a2 에 튜플이 분해되서 하나씩 들어감
a1, a2 = (12)
print(f'a1, a2 = {a1}, {a2}')
 
b2, b1 = a1, a2
print(f'b1, b2 = {b1}, {b2}')
cs

이렇게 편리하게 값을 스왑할 수 있습니다.


3-4) tuple 과 반복문

당연하게도 tuple은 반복문을 이용해서 순회 할 수 있습니다.

1
2
3
4
5
t1 = ('B''l''o''c''k''D''M''a''s''k')
 
for v in t1:
    print(v)
 
cs

이렇게 편리하게 튜플의 값을 반복문 for를 이용해서 하나씩 접근이 가능합니다.


3-5) 튜플의 중첩

튜플도 2중 리스트 처럼 중첩이 가능합니다. 소괄호 안에 소괄호를 사용하면 됩니다.
접근은 [][] 이렇게 이중이면 두개의 [][]로 접근이 가능하고, 삼중이면 [][][]으로 접근이 가능합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
t1 = (12, (34))
 
# 중첩된 튜플의 순회
print('1. 튜플 중첩 반복문')
for v in t1:
    print(v)
 
 
print('\n2. 튜플 중첩 인덱싱')
print(f't1[0] = {t1[0]}')
print(f't1[1] = {t1[1]}')
print(f't1[2] = {t1[2]}')
print(f't1[2][0] = {t1[2][0]}')
print(f't1[2][1] = {t1[2][1]}')
 
cs

위처럼 중첩된 튜플은 튜플 안에 튜플이 또 있는 형태 입니다.
중첩된 튜플을 접근하기 위해서 인덱싱의 인덱싱을 사용하면 됩니다. 

[2][0] 처럼 [2] 에 접근하면 튜플에 접근하는 것이기 때문에 또다시 [0] 을 이용해서 내부의 튜플의 첫번쨰 인자에 접근을 하게 됩니다.


3-6) tuple 타입 변환 (리스트와 형변환 자유로움)

튜플을 생성할때 혹은 튜플로 타입을 변환할때 iterable한 객체는 튜플로 편하게 변환할 수 있습니다.
여기서 iterable 한 객체는 반복 가능한 객체로써 리스트(list), 딕셔너리(dict), 집합(set), 문자열(str) 등을 말합니다.
바로 예제로 확인하시죠.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 리스트를 튜플로
a1 = [1357911]
a2 = tuple(a1)
 
print(f'tuple(리스트) = {a2}')
 
 
# 문자열을 튜플로
b1 = "BlockDMask"
b2 = tuple(b1)
 
print(f'tuple(문자열) = {b2}')
 
 
# 딕셔너리를 튜플로
c1 = {'name''blockdmask''phone''010-1234-1234''phone_type''galaxy'}
c2 = tuple(c1)
c3 = tuple(c1.values())
 
print(f'tuple(딕셔너리) = {c2}')
print(f'tuple(딕셔너리.values()) = {c3}')
 
cs

이렇게 리스트, 문자열, 딕셔너리를 튜플 타입으로 변경할 수 있습니다.
딕셔너리는 키값과 value 값을 따로 해야한다는점을 알아두시면 좋을것 같습니다.

어떤가요? 리스트와 비슷하지만 비슷하지 않은 튜플. 학습이 되었나요?
오늘의 포스팅 파이썬 튜플(python tuple)은 여기서 마치도록하겠습니다.

반응형