1 파이썬의 자료 구조
1.1리스트
리스트(list)는 순서가 있는 변수 객체의 모음이고 변경 가능 객체입니다.
>>> a = [1, 2, 3]
>>> a[1] = 4
>>> a
[1, 4, 3]
a에 [1, 2, 3]을 할당한 다음 1번 인덱스 값을 4로 변경했습니다. 이때 어떤 일이 일어나는지 그림으로 살펴보겠습니다.
그림 부록-1은 a라는 리스트가 생성되었을 때 리스트가 메모리에 어떻게 위치하는지 보여 줍니다. 리스트는 변수의 모음입니다. 1장에서 파이썬의 변수에 대해 알아보았으니 이 그림은 쉽게 이해가 될 것입니다.
그림 부록-1 리스트: 변경 가능 객체 ①
그림 부록-2는 a의 1번 인덱스에 4라는 값을 할당했을 때 모습입니다.
그림 부록-2 리스트: 변경 가능 객체 ②
리스트 안의 값을 변경했을 때 새로운 리스트를 다시 할당하는 것이 아니라 해당 인덱스만 새로운 값을 다시 참조합니다. 이처럼 값을 변경할 수 있는 자료 구조를 변경 가능 객체라고 합니다. 리스트와 딕셔너리가 여기에 해당합니다.
■ 리스트의 쓰임
내장 함수를 사용하지 않고도 리스트의 마지막에 요소를 추가할 수 있습니다.
>>> a = [1, 2, 3]
>>> a += [4, 5]
>>> a
[1, 2, 3, 4, 5]
a에 [1, 2, 3]을 할당하고 반복자 객체인 리스트 [4, 5]를 더하면 a의 마지막에 요소가 추가됩니다. 반복자 객체면 추가할 수 있으므로 튜플, 문자열, 딕셔너리도 사용할 수 있습니다.
리스트의 마지막이 아닌 중간에도 요소를 삽입할 수 있습니다.
>>> a = [1, 3, 4]
>>> a[1:1] = [2]
>>> a
[1, 2, 3, 4]
a가 [1, 3, 4]인 리스트가 있을 때 2가 없으니 1 다음 인덱스에 2를 삽입하려고 합니다. 이때는 a[1:1]과 같이 슬라이싱을 통해 [2]를 삽입하면 3, 4를 뒤로 밀어내고 그 자리에 2를 삽입합니다. 이때 삽입하는 객체는 반복자 객체여야 합니다.
요소를 삭제할 때도 내장 함수를 사용하지 않고 지울 수 있습니다.
>>> a = [1, 2, 3, 4, 5]
>>> a[2:4] = []
>>> a
[1, 2, 5]
a에 [1, 2, 3, 4, 5]를 할당하고 a의 인덱스 2부터 3까지는 빈 리스트의 요소를 채우므로 삭제됩니다.
TIP 슬라이싱이므로 인덱스 4는 포함되지 않습니다.
■ 리스트 내장 함수
유용하게 쓰이는 리스트의 내장 함수를 알아보겠습니다. 우선 삽입과 관련된 함수에는 다음 세 가지 함수가 있습니다.
• append()
• extend()
• insert()
예제로 알아볼까요? append() 함수는 리스트의 맨 끝에 객체를 추가합니다.
>>> a = [1, 2, 3]
>>> a.append(4)
>>> a
[1, 2, 3, 4]
한 번에 요소를 여러 개 추가하고 싶을 수 있습니다. 이때 추가하려는 요소가 반복자 객체라면 extend() 함수를 사용할 수 있습니다.
>>> a = [1, 2, 3]
>>> a.extend([4, 5])
>>> a
[1, 2, 3, 4, 5]
또한 insert() 함수는 첫 번째 인자로 인덱스를 받고 두 번째 인자로 삽입할 객체를 받습니다.
>>> a = [1, 3, 4]
>>> a.insert(1, 2)
>>> a
[1, 2, 3, 4]
삭제와 관련된 함수에는 다음 세 가지가 있습니다.
• clear()
• remove()
• pop()
clear() 함수는 이름처럼 리스트 안에 있는 모든 요소를 지웁니다.
>>> a = [1, 2, 3, 4]
>>> a
[1, 2, 3, 4]
>>> a.clear()
>>> a
[]
remove() 함수는 지우려는 리스트의 요소를 인자로 받습니다. 리스트 안에 같은 값이 여러 개 존재하면 가장 왼쪽에 있는 즉, 인덱스 순서상 처음에 위치한 요소만 지우고 나머지는 그대로 유지합니다.
>>> a = [1, 2, 3, 4, 2, 5, 2]
>>> a.remove(2)
>>> a
[1, 3, 4, 2, 5, 2]
remove() 함수가 요소 값 자체를 이용해 지웠다면, pop() 함수는 인덱스를 인자로 받아 요소를 삭제합니다. 아무런 인자도 전달하지 않으면 리스트의 마지막 요소를 지웁니다.
>>> a = [1, 2, 3, 4 ,5, 6]
>>> a.pop(2)
3
>>> a.pop()
6
>>> a.pop(0)
1
탐색(search)과 관련된 함수에는 count()와 index() 함수가 있습니다. count() 함수는 요소를 인자로 받고 요소 개수를 반환합니다.
>>> a = [1, 2, 3, 2, 2, 2, 2]
>>> a.count(2)
5
index() 함수는 찾으려는 요소 값을 인자로 전달합니다. 요소가 있으면 인덱스를 반환하고 없으면 오류를 내보냅니다.
>>> a = [1, 2, 3, 2, 4, 5, 2, 6, 7]
>>> a.index(2)
1
>>> a.index(2, 2)
3
>>> a.index(2, 4)
6
마지막으로 정렬과 관련된 sort() 함수를 살펴볼 차례입니다. sort()를 호출할 때 인자를 전달하지 않으면 리스트가 오름차순으로 정렬됩니다.
>>> a = [6, 3, 2, 1, 5, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5, 6]
sort() 함수에는 key와 reverse 인자를 전달할 수 있습니다. reverse를 True로 하면 내림차순으로 정렬됩니다.
>>> a.sort(reverse = True)
>>> a
[6, 5, 4, 3, 2, 1]
key는 어떻게 정렬할지 결정하는 인자입니다. 리스트 요소를 짝수와 홀수로 정렬하고 싶다면 어떻게 해야 할까요?
evenPred() 함수는 숫자를 입력받아 그것을 2로 나눈 나머지를 반환합니다. 짝수라면 0을 반환하고 홀수라면 1을 반환합니다. 이 함수를 sort() 함수의 인자 key에 전달하면 리스트의 각 요소에 대해 2로 나눈 값을 가지고 정렬을 시작합니다. 0과 1을 기준으로 정렬하므로 오름차순에 의해 evenPred() 함수에서 0을 반환하는 짝수는 리스트 앞부분에, 1을 반환하는 홀수는 리스트 뒷부분에 정렬됩니다.
>>> a
[1, 2, 3, 4, 5, 6]
>>> def evenPred(num):
return num%2
>>> a.sort(key = evenPred)
>>> a
[2, 4, 6, 1, 3, 5]
lambda 함수를 활용하면 다음과 같이 간략하게 바꿀 수 있습니다.
>>> a
[1, 2, 3, 4, 5, 6]
>>> a.sort(key = lambda x : x % 2)
>>> a
[2, 4, 6, 1, 3, 5]
■ 리스트 컴프리헨션
리스트 컴프리헨션(list comprehension)을 이용하면 리스트를 쉽게 만들 수 있습니다. 리스트 컴프리헨션을 이용해 1부터 100까지의 정수를 요소로 갖는 리스트를 만들어 봅시다.
for 문을 [ ](대괄호) 안에서 넣어 리스트를 쉽게 생성할 수 있는데 이러한 문법을 리스트 컴프리헨션이라고 합니다.
>>> li2 = [e for e in range(1, 101)]
>>> li2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
리스트 컴프리헨션에는 조건문도 추가할 수 있습니다. 예를 들어 1부터 100까지의 수에서 짝수만 뽑은 리스트가 필요하다면 다음과 같이 만들 수 있습니다. 리스트 컴프리헨션 마지막에 있는 if 문이 보이나요? 이 if 문으로 for 문에서 생성된 요소 e가 조건에 맞는지 확인한 다음 리스트에 추가합니다.
>>> li4 = [e for e in range(1, 101) if e % 2 = = 0]
>>> li4
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]
이처럼 리스트 컴프리헨션을 사용하면 리스트를 훨씬 쉽게 만들 수 있습니다. 다음 절에서는 파이썬에서 리스트만큼 유용하게 활용되는 딕셔너리에 대해서 간략히 정리해 보겠습니다.