먼저 리스트를 조작하는 메서드(method)에 대해서 알아보자. 메서드는 객체에 속한 함수를 뜻하는데 자세한 내용은 뒤에서 설명하겠다. 파이썬에서 제공하는 리스트 메서드는 여러가지가 있지만 여기선 자주 사용하는 메서드르 다루겠다.
append
)append
는 리스트 끝에 요소 하나를 추가한다.
a = [10, 20, 30]
a.append(40)
print(a)
[10, 20, 30, 40]
물론 빈 리스트에 요소를 추가할 수도 있다.
a = []
a.append(10)
print(a)
[10]
append
괄호 안에 만약에 요소가 아니라 리스트를 넣으면 어떻게 될까? 바로 리스트 안에 리스트가 추가가 된다.
a = [10, 20, 30]
a.append([500, 600])
print(a)
print(len(a))
[10, 20, 30, [500, 600]]
4
특이한 점은 리스트를 하나의 요소로 본다는 점이다. 그렇기 때문에 len(a)
를 했을 때 4가 나온다.
즉, append
는 항상 리스트 길이가 1씩 증가한다.
extend
)그렇다면 리스트에 여러개의 요소를 추가할 때는 어떻게 할까? 가장 1차원적인 생각으로는 append
를 여러번 사용하는 방법이다. 하지만 이는 비효율적이고 추가할 요소가 많다면 매우 불편하다. 이럴때는 extend
를 사용한다.
a = [10, 20, 30]
a.extend([500, 600])
print(a)
print(len(a))
[10, 20, 30, 500, 600]
5
extend
는 리스트 끝에 다른 리스트를 연결하여 리스트를 확장한다. 위 코드는 [10, 20, 30] 리스트에 [500, 600] 리스트를 연결하여 [10, 20, 30, 500, 600] 리스트가 된 것이다.
메서드를 호출한 리스트(위 코드에서는 a
가 된다) 가 변경되고 새 리스트가 생성되는 것이 아니다.
insert
)지금까지 봤던 메서드들 (append
, extend
) 들은 리스트 끝에 요소를 추가하였다. 그렇다면 우리가 원하는 위치에 요소를 추가할 수는 없을까? 이럴때 사용하는 메서드가 insert
이다.
a = [10, 20, 30]
a.insert(1, 15)
print(a)
[10, 15, 20, 30]
insert(인덱스, 요소)
는 특정 인덱스에 요소를 추가할 수 있다. 위 코드는 '1'번 인덱스에 '15'요소를 추가한 것이다. 인덱스는 0부터 시작하기 때문에 두 번째에 '15' 요소가 추가 된 것을 볼 수 있다.
insert
에서 자주 사용하는 패던은 다음과 같다.
a = [10, 20, 30]
a.insert(len(a), 40)
print(a)
[10, 20, 30, 40]
위 방법은 insert
를 이용하여 리스트 끝에 요소를 추가하는 패턴인데, 사실 위 코드는 a.append(40)
가 완벽히 동일한 작업을 한다.
그렇다면 특정 위치에 여러 요소들을 추가하는 방법은 뭐가 있을까? 바로 이전에 슬라이스를 이용하여 요소 추가했던 방법을 사용하면 된다.
a = [10, 20, 30]
a[1:1] = [15, 16, 17]
print(a)
[10, 15, 16, 17, 20, 30]
a[1:1]
과 같이 시작 인덱스와 끝 인덱스를 같게 지정하면 해당 인덱스의 요소를 덮어씌우지 않으면서 새로운 요소들을 추가할 수 있다.
이번에는 리스트에서 요소를 삭제하는 방법이다. 요소를 삭제하는 두 가지 메서드가 있다.
pop
: 마지막 요소 또는 특정 인덱스의 요소를 삭제remove
: 특정 값을 찾아서 삭제pop
)pop()
은 마지막 요소를 삭제한 뒤 삭제한 요소를 반환한다.
a = [10, 20, 30]
print(a.pop())
print(a)
30
[10, 20]
위 코드는 [10, 20, 30] 리스트에서 마지막 요소인 30 을 pop
함수로 삭제한 뒤에 반환한 것이다. 따라서 30이 출력되고 리스트를 출력할 때는 마지막 요소가 빠진 [10, 20] 이 출력된다.
그렇다면 특정 인덱스의 요소를 삭제할 때는 어떻게할까? 바로 괄호 안에 인덱스값을 넣어주면된다.
a = [10, 20, 30]
print(a.pop(1))
print(a)
20
[10, 30]
pop
괄호 안에 인덱스값 '1' 을 넣어주어 1 번 인덱스에 있는 '20'이 삭제되어 반환된 것을 볼 수 있고 실제로 리스트를 출력했을 때 리스트에 '20' 이 삭제된 것을 볼 수 있다.
remove
)이번에는 특정 값을 찾아서 삭제해보자. pop
이나 del
은 특정 인덱스를 이용하여 값을 삭제했는데 리스트에서 원하는 값을 삭제하고 싶은 경우도 있을 것이다. 그럴때는 remove
를 사용하면 된다.
a = [10, 20, 30]
a.remove(20)
print(a)
[10, 30]
remove(값)
은 리스트에서 특정 값을 찾아 삭제한다. 위 코드에서는 20 인 요소를 찾아서 삭제한 것이다. pop
과 다르게 remove
는 삭제한 값을 반환하지는 않는다. 그래서 실제로 print(a.remove(20))
을 하면 None
이 출력된다.
그렇다면 만약 리스트에 같은 값이 여러개 있으면 어떻게 될까?
a = [10, 20, 30, 20]
a.remove(20)
print(a)
[10, 30, 20]
만약 같은 값이 여러개 있을 때는 가장 처음 찾은 값이 삭제된다. 따라서 위 코드는 1번 인덱스에 있던 20이 삭제된 것이다.
지금까지 알아봤던 메서드들을 가지고 스택과 큐를 만들 수 있다. 다음과 같이 append
와 pop
을 호출하는 그림은 90도로 돌리면 스택의 모습이다.(한쪽으로 들어가고, 한쪽으로 나온다)
여기서 pop()
대신 pop(0)
을 사용한다면 바로 큐가 된다.
물론 pop(0), append()
가 아닌 pop(), insert(0, 요소)
를 사용해서도 추가/삭제를 반대로 해도 큐가 된다.
파이썬에서 스택은 리스트를 그대로 이용해도 되지만 큐는 좀 더 효율적으로 사용할 수 있도록 덱(deque : double ended queue) 라는 자료형을 제공한다. 덱은 양쪽 끝에서 추가/삭제가 가능한 구조이다.
>>> from collections import deque # collections 모듈에서 deque를 가져온다.
>>> a = deque([10, 20, 30])
>>> a
deque([10, 20, 30])
>>> a.append(500) # 덱의 오른쪽에 500 추가
>>> a
deque([10, 20, 30, 500])
>>> a.popleft() # 덱의 왼쪽 요소 하나 삭제
10
>>> a
deque([20, 30, 500])
deque의 append
는 덱 오른쪽에 요소를 추가하고 popleft
는 덱의 왼쪽 요소를 삭제한다. 반대로 appendleft
는 덱 왼쪽에 요소를 추가하고 pop
은 덱의 오른쪽 요소를 삭제할 수 있다.
index
)a = [10, 20, 30, 20, 40]
print(a.index(20))
1
index(값)
은 리스트에서 특정 값의 인덱스를 찾는다. 이때 같은 값이 여러개 있을 경우 가장 처음 찾은 값의 인덱스를 구한다.
count
)a = [10, 20, 30, 20, 40]
print(a.count(20))
2
reverse
)>>> a = [10, 20, 30, 15, 20, 40]
>>> a.reverse()
>>> a
[40, 20, 15, 30, 20, 10]
sort
)>>> a = [10, 20, 30, 15, 20, 40]
>>> a.sort()
>>> a
[10, 15, 20, 20, 30, 40]
기본적으로는 오름차순으로 정렬이 된다. 만약 내림차순으로 정렬하고 싶다면 sort(reverse=True)
를 한다.
>>> a = [10, 20, 30, 15, 20, 40]
>>> a.sort(reverse=True)
>>> a
[40, 30, 20, 20, 15, 10]
sort
와 내장함수 sorted
의 차이파이썬에서는 sort
메서드 뿐만 아니라 내장함수 sorted
도 제공이 된다. 이 둘은 모두 정렬해주는 함수이지만 약간의 차이점이 존재하는데 sort
는 사용한 리스트를 변경하지만 sorted
는 정렬된 새 리스트를 생성한다.
>>> a = [10, 20, 30, 15, 20, 40]
>>> a.sort()
>>> a
[10, 15, 20, 20, 30, 40]
>>> a = [10, 20, 30, 15, 20, 40]
>>> sorted(a)
[10, 15, 20, 20, 30, 40]
>>> a
[10, 20, 30, 15, 20, 40]
clear
)clear
은 모든 리스트의 요소들을 삭제한다.
>>> a = [10, 20, 30]
>>> a.clear()
>>> a
[]
따라서 위 코드에서 a
는 빈 리스트가 된다.
clear
함수 말고도 del a[:]
와 같이 시작 인덱스와 끝 인덱스를 생략하여 빈 리스트를 만드는 방법도 있다.
>>> a = [10, 20, 30]
>>> del a[:]
>>> a
[]
리스트에서는 메서드를 이용하지 않고 슬라이스로 조작할 수도 있다. 다음은 리스트 끝에 요소가 한 개 있는 리스트를 추가한다.
>>> a = [10, 20, 30]
>>> a[len(a):] = [500]
>>> a
[10, 20, 30, 500]
a[len(a):]
는 시작 인덱스가 len(a)
로 리스트의 마지막 인덱스보다 1 큰 값이다. 즉 리스트에 끝에서부터 시작하겠다는 말이다.(이때는 리스트의 범위를 벗어난 인덱스를 사용할 수 있다.)
a[len(a):] = [500]
과 같이 한 개 리스트가 들어있는 리스트를 할당하면 리스트 a
끝에 값을 한 개 추가하며 a.append(500)
과 같다.
그리고 a[len(a):] = [500, 600]
을 하면 a.extend([500, 600])
과 같다.
>>> a = [10, 20, 30]
>>> a[len(a):] = [500, 600]
>>> a
[10, 20, 30, 500, 600]
리스트(시퀀스 객체)가 비어 있는지 확인하려면 어떻게 해야할까? 방법은 간단하다. 리스트는 len
함수로 길이를 확인할 수 있다는 사실을 이용하면 된다. 이를 이용하여 if
조건문으로 판단하면 리스트가 비어있는지 확인할 수 있다.
if not len(seq): # 리스트가 비어 있으면 True
if len(seq): # 리스트에 요소가 있으면 True
하지만 파이썬에서는 이보다 간단하게 그냥 리스트(시퀀스 객체) 를 바로 if
조건문으로 판단하는 방법을 권장한다.
if not seq: # 리스트가 비어 있으면 True
if seq: # 리스트에 내용이 있으면 True
리스트가 비어있는지 확인하는 방법으로 리스트의 마지막 인덱스에 접근하는 방법이 있다. 인덱스를 -1 지정하면 마지막 인덱스에 접근한다는 것을 알고 있을 것이다.
>>> seq = [10, 20, 30]
>>> seq[-1]
30
그런데 만약에 빈 리스트에서는 -1 를 활용하여 리스트에 접근하면 오류가 발생한다.
>>> a = []
>>> a[-1]
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
a[-1]
IndexError: list index out of range
이럴경우를 대비해 if
문을 활용하여 리스트에 요소가 있을 때 마지막 요소에 접근하도록 다음과 같이 코드를 작성할 수 있다.
seq = []
if seq: # 리스트에 요소가 있는지 확인
print(seq[-1]) # 요소가 있을 때만 마지막 요소를 가져옴