Python의 데이터타입중 list와 tuple에 대해 정리합니다.
개요
- 데이터 타입중 ‘list’와 ‘tuble’ 과 관련된 다양한 기능을 정리합니다.
리스트 & 튜플
-
복수개의 값을 담을 수 있는 데이터 구조
-
실생활에서 사용하는 리스트(학생 리스트, 성적 리스트 등등)과 동일한 의미로 이해
-
list - mutable (생성된 후에 변경 가능)
-
tuple - immutable (생성된 후에 변경 불가능)
공통점
-
리스트와 튜플은 모두 인덱싱과 슬라이싱이 가능하다.
-
순회가능(iterable) - 리스트와 튜플은 모두 for문을 이용해 순회할 수 있다.
차이점
-
리스트의 요소는 (생성 후)바꿀 수 있으나(mutable), 튜플의 요소는 (생성 후)바꿀 수 없다.(immutable)
-
리스트보다는 튜플의 순회속도가 약간 더 빠르다.
리스트
리스트 초기화
-
[] 안에 값을 담아서 생성
-
list() 함수로 생성
-
str.split()함수로 생성 되기도 한다.
1
2
L1 = []
print(L1)
[]
1
2
L1 = [1, 2, 3, 5, 10]
print(L1)
[1, 2, 3, 5, 10]
1
2
L1 = ['korea', 'seoul', 1, 23, [34, 56]]
print(L1)
['korea', 'canada', 1, 23, [34, 56]]
1
2
3
4
L1 = hello word
L2 = L1.str.split()
print(L2)
list() 함수
- 다른 데이터 타입을 리스트로 변환할 때도 사용
1
2
3
L1 = 'hello world' # 문자열 데이터
L2 = list(L1) #리스트 형으로 변경 -> 하나의 문자별로 각각 리스트의 값이 된다.
print(L2)
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
1
2
3
4
L3 = (1, 2, 3) #int형 데이터
L4 = list(L3) #리스트 형으로 변경
print(L4)
[1, 2, 3]
string split 함수
-
구분자로 구분되는 리스트를 반환 (실제로 자주 사용 됨)
-
split() 의 () 안에 입력되는 특정 값을 기준으로 분류된다.
-
아무것도 입력하지 않고 ()을 하거나 (‘ ‘)로 입력하면 1칸 공백을 기준으로 split한다.
1
2
3
4
5
6
7
8
L1 = 'hello world nice weather'
L2 = L1.split()
L3 = 'today is shiny day'
L4 = L3.split(' ')
print(L2)
print(L4)
['hello', 'world', 'nice', 'weather'] ['today', 'is', 'shiny', 'day']
리스트 indexing
-
문자열의 인덱싱과 동일하게 동작
-
[] 연산자를 이용하여 항목을 얻어온다.
-
List[i] : List 의 i번째 원소를 반환 (0부터 시작, 역순인 경우 -1부터 시작)
-
i가 음수인 경우도 가능하며 마지막원소가 -1로 하여 앞으로 갈때마다 1씩 감소함
1
2
3
4
L1 = [1, 2, 3, 4, 5, 6]
print(L1[2]) # L1 리스트에서 2번째 인덱스 -> 3번째 수
print(L1[5])
print(L1[-1])
3 6 6
리스트 개별 아이템에 접근
- 인덱스에 접근하여 값을 업데이트 가능
1
2
L1 = 'hello world'
print(L1[0])
h
1
2
3
4
L2 = 'jello world'
L3 = 'j' + L1[1:] #1번재 인덱스 부터 끝까지 => ello world
print(L3)
jello world
1
2
3
4
L4 = L1.replace('h', 'j')
print(L4) # L1의 h를 j로 치환한 결과를 출력
print(L1) # 기존의 L1출력 <- L4는 L1를 활용해 변수선언을 한 것 뿐이지, L1 에 직접적인 변화를 주지는 않았다.
jello world hello world
1
2
3
4
5
L1 = [1, 2, 3, 4, 5]
L1[0] = 100 # 0번째 인덱스인 1을 100으로 변경
L1[-1] = 90 # 맨 마지막 인덱스인 5를 90으로 변경
print(L1)
[100, 2, 3, 4, 90]
리스트 slicing
-
문자열 슬라이싱과 동일하게 동작
-
슬라이싱의 결과 역시 list!
-
List[start:end,step] 순서로 입력
-
start 인덱스 부터 end인덱스 까지 step만큼 건너 뛴 부분을 리스트로 반환
-
step은 defL1ult가 1
-
start와 end도 입력하지 않아도 된다. 단, ‘:’은 반드시 넣어야 한다.
-
1
2
3
4
5
6
7
8
9
10
L1 = [1, 2, 3, 4, 5, 6, 7, 8]
print(L1[4:7])
print(L1[:7])
print(L1[3:])
print(L1[:])
# slicing
# start:end:increment(1)
L1[1:7]
[5, 6, 7] [1, 2, 3, 4, 5, 6, 7] [4, 5, 6, 7, 8] [1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 5, 6, 7]
list 멤버 함수
-
생성된 리스트 객체에 동작하는 함수
-
추후, 클래스와 멤버 함수 개념을 정리할 예정
append() - 요소 추가 함수
- 리스트의 끝에 항목을 추가함
1
2
3
4
L1 = [1, 2, 3, 4, 5]
L1.append(10)
print(a)
[1, 2, 40, 30, 5]
extend() - 요소 추가 함수
-
리스트를 연장
-
+= 로도 가능함
1
2
3
4
5
6
7
L2 = [1, 2, 3, 4, 5]
L3 = [6, 7, 8, 9, 10]
L2.extend(L3)
print(L2)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1
2
3
4
5
6
# a.extend(b)와 동일
L2 = [1, 2, 3, 4, 5]
L3 = [6, 7, 8, 9, 10]
L2 += L3
print(L2)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
insert() - 요소 추가 함수
-
리스트의 원하는 위치에 추가 가능
-
앞에 인덱스를, 뒤에 아이템을 명시
1
2
3
4
L4 = [1, 3, 4, 5, 6]
L4.insert(1, 40) # 1번째 인덱스에 40을 넣는다.
print(L4)
[1, 40, 3, 4, 5, 6]
remove() - 요소 제거 함수
-
값으로 항목 삭제
-
한 리스트에 동일값이 있을 경우 remove 앞쪽의 인덱스에 있는 값이 삭제 된다.
1
2
3
L5= [1, 2, 30, 40, 30, 5]
L5.remove(9)
print(L5) # list에 9가 없기 때문에 에러가 발생
1
2
L5.remove(30)
print(L5) # list에 있는 30중 앞쪽 인덱스의 30이 삭제 되었다.
[1, 2, 40, 30, 5]
pop() - 요소 제거 함수
-
지우고자 하는 아이템을 반환 후, 삭제
-
()에 들어가는 숫자는 인덱스 번호
1
2
3
4
5
L5 = [1, 2, 3, 4, 5]
L6 = L5.pop(1) #1번째 인덱스 값을 반환 후 삭제
print(L5)
print(L6)
[1, 3, 4, 5] 2
순서상 L5의 1번째 인덱스값을 지우는 L6가 먼저 선언되어서 L5에서 1번째 인덱스값인 2가 사라진다.
index() - 요소 위치 찾기 함수
- 찾고자 하는 값의 인덱스 반환
1
2
3
4
5
L7 = [1, 3, 2, 1, 4]
print("1의 위치:{}".format(L7.index(1)))
print("3의 위치:{}".format(L7.index(3)))
L7.index(5) # 5의 위치: 없으므로 Error 발생 (5 is not in list)
1의 위치:0 3의 위치:1
replace()
-
개별 아이템 접근에서 정리한 내용과 동일
-
인덱스로 접근하여 특정값을 변경 가능 (mutable)
1
2
3
4
5
6
L1 = 'hello world'
L4 = L1.replace('h', 'j')
print(L4) # L1의 h를 j로 치환한 결과를 출력
print(L1) # 기존의 L1출력 <- L4는 L1를 활용해 변수선언을 한 것 뿐이지, L1 에 직접적인 변화를 주지는 않았다.
jello world hello world
in 키워드
-
리스트 내에 해당 값이 존재하는지 확인
-
value in [list]
-
True, False 중 한가지로 반환
1
2
3
4
5
6
L1 = [1, 2, 3, 4, 5, 10]
L2 = 10
L3 = L2 in a # False
print(L3)
False
list 정렬
-
sort() -> 리스트 자체를 내부적으로 정렬
-
sorted() -> 리스트의 정렬된 복사본을 반환
sorted : 원본 데이터를 보존하고자 할때 유용
1
2
3
4
5
L1 = [9, 10, 7, 19, 1, 2, 20, 21, 7, 8]
L1.sort(reverse=True)
L2 = sorted(L1)
print(L1)
print(L2)
[21, 20, 19, 10, 9, 8, 7, 7, 2, 1] [1, 2, 7, 7, 8, 9, 10, 19, 20, 21]
tuple
-
리스트와 달리 ()로 표현한다.
-
리스트와 같이 복수개의 값을 갖는 컬렉션 타입
-
한번 생성하면 변경이 불가능하다.(immutable)
-
즉, indexing으로 개별접근을 해도 값의 추가, 변경, 삭제는 불가능 하다.
1
2
3
4
5
L1 = [1, 2, 3]
T1 = (1, 2, 3)
print(type(L1))
print(type(T1))
<class 'list'> <class 'tuple'>
1
2
3
4
L1[0] = 100 # 0번째 index 자리에 100을 추가
print(L1)
# 리스트는 변경이 가능 (Mutable)
[100, 2, 3]
1
2
b[0] = 100 # 튜플은 변경이 불가능하다!
print(b)
튜플 indexing
1
2
3
4
5
6
# 인덱싱과 슬라이싱
T = [4, 5, 1, 2, 10, 6]
print("T[2] = {}".format(T[2]))
print("T[4] = {}".format(T[4]))
print("T[-1] = {}".format(T[-1]))
T[2] = 1 T[4] = 10 T[-1] = 6
튜플 slicing
1
2
3
4
5
6
T = [4, 5, 1, 2, 10, 6]
print("T[0:3] = {}".format(T[0:3]))
print("T[:3] = {}".format(T[:3]))
print("T[2:] = {}".format(T[2:]))
print("T[0:4:2] = {}".format(T[0:4:2]))
T[0:3] = [4, 5, 1] T[:3] = [4, 5, 1] T[2:] = [1, 2, 10, 6] T[0:4:2] = [4, 1]
1
튜플 관련 함수
소괄호 없이 생성
1
2
3
4
# 소괄호 없이 튜플 생성할 수 있다.
T = 1, 2, 3, 4
print(T)
(1, 2, 3, 4)
원소가 1개인 튜플 만들기
1
2
3
4
# 원소가 하나인 튜플은 반드시 원소 뒤에 쉼표를 붙여야 한다.
T = 1,
print(type(T))
print(T)
<class 'tuple'> (1,)
함수의 가변 인자로 활용
- 아직 함수의 내용을 정리하지 않았기에 활용 용도가 있다는 것 정도만 이해하고 넘어가면 좋겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
# 함수의 가변 인자로 사용
def f(*x): # *: 인자수가 정해지지 않았음을 의미
print("입력된 데이터의 타입:{}".format(type(x)))
sum_x = 0
product_x = 1
for val in x:
sum_x += val
product_x *= val
return sum_x, product_x
#S, P = f(1, 2, 3, 4, 5) # 출력을 각각 S와 P로 받음
S, P = f(1,2) # 출력을 각각 S와 P로 받음
print(S, P)
입력된 데이터의 타입:<class 'tuple'> 3 2
tuple unpacking
- 튜플은 괄호를 생략해도 만들 수 있다.
1
2
a = (100, 200)
type(a)
tuple
1
2
a = 100, 200
type(a)
tuple
- 이를 활용해 여러개의 변수에 여러개의 튜플의 값을 차례대로 대입시킬 수 있다.
1
2
a, b, c, d = 100, 200, 300, 400
print(a, b, c, d)
100 200 300 400
튜플형태의 a와 b의 값을 교환하려면?
1
2
3
4
a = 5
b = 4
print(a, b)
5 4
1
2
3
4
5
6
# 잘못된 예시
a = b #b를 a에 대입 -> a가 b의 값으로 업데이트 됨
b = a # b를 a에 대입 -> 이미 b의 값이 업데이트된 a (사실상 b)가 b에 업데이트 되는 것
print(a, b)
4 4
1
2
3
4
5
6
7
8
9
10
11
12
13
# 올바른 예시 - 일반적인 programming 방식
a = 5
b = 4
print(a,b)
# logic
temp = a # 임시로 어떤 값에 a를 입력해둔다.
a = b # a를 b의 값으로 업데이트 시킨다.
b = temp # b의 값을 임시로 입력해둔 temp(즉 원래의 a값) 으로 업데이트 시킨다.
print(a,b)
5 4 4 5
tuple unpacking 을 통해 이 과정을 한번에 해결 할 수 있다. (파이썬에서 자주 tuple이 가장 많이 사용되는 예시)
1
2
3
4
5
6
7
8
a = 5
b = 4
print(a,b)
a, b = b, a
print(a, b)
5 4 4 5
List와 Tuple의 공통점
공통점 1. Indexing과 Slicing이 가능하다.
-
리스트와 튜플 모두 인덱싱과 슬라이싱이 가능하다.
-
관련 내용은 위에서 개별적으로 증명하였기에 따로 정리하지 않음
공통점 2. for문을 이용한 순회가 가능하다(iterable)
-
for data in List:
-
for data in Tuple:
-
즉, max, min등의 순회 가능한 요소를 입력받는 함수의 입력으로 사용할 수 있다. (추후 ‘함수’ 관련 파트에서 더 자세하게 다룰 예정)
1
2
3
4
5
6
7
8
9
10
11
# for문을 이용한 순회
L = [1, 2, 3, 4, 5]
T = (1, 2, 3, 4, 5)
print("List 순회")
for val in L:
print(val ** 2) #val의 제곱을 출력
print("\nTuple 순회")
for val in T:
print(val ** 2) #val의 제곱을 출력
List 순회 1 4 9 16 25 Tuple 순회 1 4 9 16 25
List와 Tuple의 차이점
차이점 1. 가변(mutable)과 불변(immutable)
-
위에서 증명했듯이 list 는 요소를 바꿀 수 있지만, tuple은 불가능하다.
-
이러한 차이 때문에 list는 dict의 key로 사용될 수 있지만, tuple은 불가능 하다.
-
조건을 입력해서, 해당 조건에 대응되는 값들을 출력하는 사전 구축은 데이터 전처리에서 자주 사용되는 기능이다. (추후 전처리에서 자세히 설명 예정)
차이점 2. Tuple의 순회속도가 List보다 조금 더 빠르다.
-
요소 변경이 필요없고, 요소에 대한 연산 결과 만 필요한 경우는 리스트 보다는 튜플이 더 적합하다.
-
보통 (데이터가 큰 경우에 한해) 리스트로 작업 후, 튜플로 자료형을 바꾼 뒤 순회를 한다.
1
2
3
# 순회 속도 비교하기
large_L = list(range(100000000)) # 100000000개의 값이 담긴 리스트 생성
large_T = tuple(range(100000000)) # 100000000개의 값이 담긴 튜플 생성
1
2
3
# time 모듈의 time 함수 사용 : 현재시간을 반환해주는 함수
import time
time.time()
1625271172.8716881
1
2
3
4
5
6
7
# 리스트 순회 속도 측정
import time
start_time = time.time()
for val1 in large_L:
pass
end_time = time.time()
print(end_time - start_time)
3.0789952278137207
1
2
3
4
5
6
# 튜플 순회 속도 측정
start_time = time.time()
for val2 in large_T:
pass
end_time = time.time()
print(end_time - start_time)
3.0692572593688965
리스트를 튜플로 변환 후 순회
-
리스트 -> 튜플 : tuple(list)
-
튜플 -> 리스트 : list(tuple)
1
large_T2 = tuple(large_L) #large_L 을 튜플로 변경해 large_T2로 변수 선언
1
2
3
4
5
6
# 튜플 순회 속도 측정
start_time = time.time()
for val2 in large_T2:
pass
end_time = time.time()
print(end_time - start_time)
3.0806164741516113
댓글남기기