11.3 인덱스 사용하기
이번에는 시퀀스 객체에 들어있는 요소에 접근하는 방법을 알아보겠습니다. 시퀀스 객체의 각 요소는 순서가 정해져 있으며, 이 순서를 인덱스라고 부릅니다.
다음과 같이 시퀀스 객체에 [ ](대괄호)를 붙이고 [ ] 안에 각 요소의 인덱스를 지정하면 해당 요소에 접근할 수 있습니다.
- 시퀀스객체[인덱스]
간단하게 리스트를 만든 뒤 요소를 출력해보겠습니다.
>>> a = [38, 21, 53, 62, 19] >>> a[0] # 리스트의 첫 번째(인덱스 0) 요소 출력 38 >>> a[2] # 리스트의 세 번째(인덱스 2) 요소 출력 53 >>> a[4] # 리스트의 다섯 번째(인덱스 4) 요소 출력 19
인덱스(index, 색인)는 위치 값을 뜻하는데 국어사전 옆면에 ㄱ, ㄴ, ㄷ으로 표시해 놓은 것과 비슷합니다. 여기서 주의할 점은 시퀀스 객체의 인덱스는 항상 0부터 시작한다는 점입니다(대다수의 프로그래밍 언어는 인덱스가 0부터 시작합니다). 따라서 리스트 a의 첫 번째 요소는 a[0]이 됩니다. 꼭 기억해두세요.
튜플, range, 문자열도 [ ]에 인덱스를 지정하면 해당 요소를 가져올 수 있습니다.
다음은 튜플 b의 첫 번째(인덱스 0) 요소를 출력합니다.
>>> b = (38, 21, 53, 62, 19) >>> b[0] # 튜플의 첫 번째(인덱스 0) 요소 출력 38
range도 인덱스로 접근할 수 있습니다. 다음은 range의 세 번째(인덱스 2) 요소를 출력합니다.
>>> r = range(0, 10, 2) >>> r[2] # range의 세 번째(인덱스 2) 요소 출력 4
문자열은 요소가 문자이므로 인덱스로 접근하면 문자가 나옵니다. 다음은 문자열 hello의 여덟 번째 요소를 출력합니다.
>>> hello = 'Hello, world!' >>> hello[7] # 문자열의 여덟 번째(인덱스 7) 요소 출력 'w'
시퀀스 객체에 인덱스를 지정하지 않은 상태는 해당 객체 전체를 뜻합니다. 따라서 다음과 같이 리스트 a를 출력하면 [ ]를 포함하여 리스트 전체가 출력됩니다.
>>> a = [38, 21, 53, 62, 19] >>> a # 시퀀스 객체에 인덱스를 지정하지 않으면 시퀀스 객체 전체를 뜻함 [38, 21, 53, 62, 19]
시퀀스 객체에서 [ ](대괄호)를 사용하면 실제로는 __getitem__ 메서드를 호출하여 요소를 가져옵니다. 따라서 다음과 같이 __getitem__ 메서드를 직접 호출하여 요소를 가져올 수도 있습니다.
시퀀스객체.__getitem__(인덱스)
>>> a = [38, 21, 53, 62, 19] >>> a.__getitem__(1) 21
__getitem__ 메서드는 '39.3 인덱스로 접근할 수 있는 이터레이터 만들기'에서 설명하겠습니다.
11.3.1 음수 인덱스 지정하기
지금까지 시퀀스 객체에 인덱스를 양수만 지정했습니다. 그러면 인덱스를 음수로 지정하면 어떻게 될까요?
>>> a = [38, 21, 53, 62, 19] >>> a[-1] # 리스트의 뒤에서 첫 번째(인덱스 -1) 요소 출력 19 >>> a[-5] # 리스트의 뒤에서 다섯 번째(인덱스 -5) 요소 출력 38
시퀀스 객체에 인덱스를 음수로 지정하면 뒤에서부터 요소에 접근하게 됩니다. 즉, -1은 뒤에서 첫 번째, -5는 뒤에서 다섯 번째 요소입니다. 따라서 a[-1]은 뒤에서 첫 번째 요소인 19, a[-5]는 뒤에서 다섯 번째 요소인 38이 나옵니다.
리스트 a의 양수 인덱스와 음수 인덱스를 그림으로 표현하면 다음과 같은 모양이 됩니다.
튜플, range, 문자열도 음수 인덱스를 지정하면 뒤에서부터 요소에 접근합니다.
다음은 튜플 b의 뒤에서 첫 번째(인덱스 -1) 요소를 출력합니다.
>>> b = (38, 21, 53, 62, 19) >>> b[-1] # 튜플의 뒤에서 첫 번째(인덱스 -1) 요소 출력 19
물론 range도 음수 인덱스로 접근할 수 있습니다. 다음은 range의 뒤에서 세 번째(인덱스 -3) 요소를 출력합니다.
>>> r = range(0, 10, 2) >>> r[-3] # range의 뒤에서 세 번째(인덱스 -3) 요소 출력 4
문자열도 음수 인덱스를 지정할 수 있습니다. 다음은 문자열 hello의 뒤에서 네 번째(인덱스 -4) 요소를 출력합니다.
>>> hello = 'Hello, world!' >>> hello[-4] # 문자열의 뒤에서 네 번째(인덱스 -4) 요소 출력 'r'
11.3.2 인덱스의 범위를 벗어나면?
시퀀스 객체를 만들면 요소의 개수는 정해져 있죠? 다음과 같이 리스트를 만든 뒤 범위를 벗어난 인덱스에 접근하면 어떻게 될까요?
>>> a = [38, 21, 53, 62, 19] >>> a[5] # 인덱스 5는 범위를 벗어났으므로 에러 Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> a[5] IndexError: list index out of range
실행을 해보면 리스트의 인덱스가 범위를 벗어났다는 IndexError가 발생합니다.
리스트 a의 요소 개수는 5개인데 a[5]와 같이 지정하면 리스트의 범위를 벗어나게 되므로 에러가 발생합니다. 왜냐하면 인덱스는 0부터 시작하므로 마지막 요소의 인덱스는 4이기 때문이죠. 즉, 마지막 요소의 인덱스는 시퀀스 객체의 요소 개수보다 1 작습니다. 이 부분은 시퀀스 객체를 사용할 때 자주 틀리는 부분이므로 꼭 기억해두세요.
마찬가지로 튜플, range, 문자열도 범위를 벗어난 인덱스를 지정하면 IndexError가 발생합니다.
11.3.3 마지막 요소에 접근하기
앞에서 시퀀스 객체에 인덱스를 -1로 지정하면 뒤에서 첫 번째 요소에 접근한다고 했죠? 바로 시퀀스 객체의 마지막 요소입니다.
그러면 시퀀스 객체의 마지막 요소에 접근하는 다른 방법은 없을까요? 다음과 같이 len 함수로 리스트의 길이를 구한 뒤 이 길이를 인덱스로 지정해보면 에러가 발생합니다.
>>> a = [38, 21, 53, 62, 19] >>> len(a) # 리스트의 길이를 구함 5 >>> a[5] # 리스트의 길이를 인덱스로 지정 Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> a[5] IndexError: list index out of range
리스트 a의 인덱스는 0부터 4까지이므로 인덱스에 a의 길이 5를 지정하면 인덱스의 범위를 벗어나게 됩니다. 따라서 5가 아닌 4를 지정해야 마지막 문자가 나옵니다.
>>> a[4] 19
그럼 조금 응용해서 인덱스에 len을 조합해보겠습니다. 다음과 같이 인덱스에 len(a)를 넣어봅니다.
>>> a[len(a)] Traceback (most recent call last): File "<pyshell#3>", line 1, in <module> a[len(a)] IndexError: list index out of range
len(a)는 5이므로 인덱스가 범위를 벗어납니다. 이때는 len(a)에서 1을 빼주어야 인덱스가 범위를 벗어나지 않습니다.
>>> a[len(a) - 1] # 마지막 요소(인덱스 4) 출력 19
마지막 요소 19가 나왔습니다. 즉, len(a) - 1은 4이므로 마지막 문자가 나옵니다. 이 방법은 시퀀스 객체의 마지막 인덱스를 구할 때 종종 사용하는 방법입니다.
11.3.4 요소에 값 할당하기
이제 시퀀스 객체의 요소에 값을 할당하는 방법을 알아보겠습니다. 시퀀스 객체는 [ ]로 요소에 접근한 뒤 =로 값을 할당합니다.
- 시퀀스객체[인덱스] = 값
먼저 리스트부터 요소에 값을 할당해보겠습니다.
>>> a = [0, 0, 0, 0, 0] # 0이 5개 들어있는 리스트 >>> a[0] = 38 >>> a[1] = 21 >>> a[2] = 53 >>> a[3] = 62 >>> a[4] = 19 >>> a [38, 21, 53, 62, 19] >>> a[0] 38 >>> a[4] 19
a[0] = 38처럼 [ ]에 인덱스를 지정한 뒤 값을 할당하면 됩니다. 단, 이때도 범위를 벗어난 인덱스는 지정할 수는 없습니다.
>>> a[5] = 90 Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> a[5] = 90 IndexError: list assignment index out of range
'10.2 튜플 사용하기'에서 튜플은 안에 저장된 요소를 변경할 수 없다고 했죠? 다음과 같이 튜플의 [ ]에 인덱스를 지정한 뒤 값을 할당하면 에러가 발생합니다.
>>> b = (0, 0, 0, 0, 0) >>> b[0] = 38 Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> b[0] = 38 TypeError: 'tuple' object does not support item assignment
마찬가지로 range와 문자열도 안에 저장된 요소를 변경할 수 없습니다.
>>> r = range(0, 10, 2) >>> r[0] = 3 Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> r[0] = 3 TypeError: 'range' object does not support item assignment >>> hello = 'Hello, world!' >>> hello[0] = 'A' Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> hello[0] = 'A' TypeError: 'str' object does not support item assignment
즉, 시퀀스 자료형 중에서 튜플, range, 문자열은 읽기 전용입니다.
11.3.5 del로 요소 삭제하기
이번에는 del로 시퀀스 객체의 요소를 삭제해보겠습니다. 요소 삭제는 다음과 같이 del 뒤에 삭제할 요소를 지정해주면 됩니다.
- del 시퀀스객체[인덱스]
먼저 리스트를 만들고 세 번째 요소(인덱스 2)를 삭제해보겠습니다.
>>> a = [38, 21, 53, 62, 19] >>> del a[2] >>> a [38, 21, 62, 19]
del a[2]와 같이 사용하면 리스트 a의 세 번째 요소(인덱스 2)인 53을 삭제합니다.
리스트와는 달리 튜플은 요소를 삭제할 수 없습니다.
>>> b = (38, 21, 53, 62, 19) >>> del b[2] Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> del b[2] TypeError: 'tuple' object doesn't support item deletion
마찬가지로 range와 문자열도 안에 저장된 요소를 삭제할 수 없습니다.
>>> r = range(0, 10, 2) >>> del r[2] Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> del r[2] TypeError: 'range' object doesn't support item deletion >>> hello = 'Hello, world!' >>> del hello[2] Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> del hello[2] TypeError: 'str' object doesn't support item deletion