누구나 다하는 파이썬 강좌 - 리스트(list)
파이썬의 리스트에 대해 다루고 있습니다.
2024. 6. 22 최초작성
2024. 7. 7
2024. 7. 21 리스트의 메소드 사용법 추가
다음 글을 기반으로 작성되었습니다.
https://docs.python.org/ko/3/tutorial/introduction.html
https://docs.python.org/ko/3/tutorial/datastructures.html
포스트에서 >>>는 파이썬 인터프리터에서 실행했음을 의미합니다.
파이썬에는 다른 데이터 타입의 값들을 포함할 수 있는 컴파운드 (compound) 데이터 타입이 있습니다. 그중에 하나가 리스트(list)로 대괄호[] 사이에 쉼표로 구분된 값들을 적습니다. 리스트는 서로 다른 데이터 타입의 값들을 포함할 수 있지만, 모두 같은 데이터 타입의 값을 사용하는 경우가 더 많습니다.
정수 값을 포함하는 리스트를 생성합니다.
>>> squares = [1, 4, 9, 16, 25]
리스트를 출력해봅니다.
>>> squares
[1, 4, 9, 16, 25]
문자열처럼 리스트도 인덱싱과 슬라이싱을 할 수 있습니다:
리스트를 생성합니다.
>>> squares = [1, 4, 9, 16, 25]
인덱싱을 사용하여 리스트의 첫번째 원소를 출력합니다.
>>> squares[0]
1
리스트의 마지막 원소를 출력합니다. 음수의 경우 마지막값부터 인덱싱합니다.
>>> squares[-1]
25
리스트의 끝에서 2번째 원소를 출력합니다.
>>> squares[-2]
16
슬라이싱하면 새로운 리스트를 생성합니다.
인덱스 1부터 인덱스 3이전까지를 슬라이싱하여 새로운 리스트를 생성합니다.
>>> squares[1:3]
[4, 9]
+연산자를 사용하여 두 개의 리스트를 결합할 수 있습니다.
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> [1, 2, 3] + [4, 5]
[1, 2, 3, 4, 5]
값을 변경할 수 없었던 문자열과 달리 리스트는 값을 변경할 수 있습니다.
>>> cubes = [1, 8, 27, 65, 125]
인덱스 3의 리스트 값을 변경합니다.
>>> cubes[3] = 64
인덱스 3의 값이 변경되었습니다.
>>> cubes
[1, 8, 27, 64, 125]
append 메소드를 사용하여 리스트 끝에 원소를 추가할 수 있습니다.
216을 리스트에 추가합니다.
>>> cubes.append(216)
리스트 끝에 216이 추가되었습니다.
>>> cubes
[1, 8, 27, 64, 125, 216]
변수의 값으로 리스트를 대입하면 리스트를 복사하지 않고 새로운 변수는 대입한 변수의 값을 참조합니다. 하나의 리스트를 참조하는 두개의 변수가 생긴셈입니다.
변수 rgb에 리스트를 대입합니다.
>>> rgb = ["Red", "Green", "Blue"]
새로운 변수 rgba에 기존 변수 rgb를 대입합니다.
>>> rgba = rgb
변수 rgba와 변수 rgb가 같은 리스트 객체를 가리키고 있기 때문에 변수의 id 값이 동일합니다.
>>> id(rgb) == id(rgba)
True
변수 rgba를 사용하여 리스트에 새로운 값을 추가합니다.
>>> rgba.append("Alph")
변수 rgb에서도 원소가 추가된것을 볼 수 있습니다.
>>> rgb
["Red", "Green", "Blue", "Alph"]
리스트에 대한 슬라이스 연산을 하면 새로운 리스트를 생성합니다. 슬라이스가 얕은 복사를 하기 때문에 새로운 리스트를 생성하긴 하지만 값은 공유합니다.
변수 rgba가 가리키는 리스트의 일부를([:]는 리스트 전체를 의미합니다) 슬라이싱하여 변수 correct_rgba에 대입합니다.
>>> correct_rgba = rgba[:]
변수 correct_rgba가 가리키는 리스트의 마지막값을 변경합니다.
>>> correct_rgba[-1] = "Alpha"
원래 변수 rgba와 슬라이싱한 변수 correct_rgba에 똑같이 값이 반영된것을 볼수 있습니다. 슬라이싱을하면 얕은 복사기 이루어져 두 변수가 리스트를 공유하기 때문입니다.
>>> correct_rgba
["Red", "Green", "Blue", "Alpha"]
>>> rgba
["Red", "Green", "Blue", "Alph"]
슬라이스에 대입하는 것도 가능한데, 리스트의 길이를 변경할 수 있고, 모든 항목을 삭제할 수조차 있습니다:
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
슬라이싱후 리스트의 값을 변경할 수 있습니다.
>>> letters[2:5] = ['C', 'D', 'E']
슬라이싱한 리스트를 변경한 것이 원본 리스트에도 반영됩니다.
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
값을 제거할 수도 있습니다. 슬라이싱한 리스트에서 값을 제거한 것이 원본 리스트에도 반영됩니다.
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
리스트의 모든 값을 제거할 수도 있습니다.
>>> letters[:] = []
>>> letters
[]
내장 함수 len()을 사용하여 리스트의 원소 개수를 확인할 수 있습니다.
>>>letters = ['a', 'b', 'c', 'd']
>>> len(letters)
4
리스트를 중첩할 수도 있습니다. 리스트를 포함하는 리스트를 만듭니다.
2개의 리스트를 생성합니다.
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
리스트안에 리스트를 넣습니다.
>>> x = [a, n]
리스트안에 리스트가 있는 경우 접근하는 예입니다.
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
리스트의 첫번째 값도 리스트입니다.
>>> x[0]
['a', 'b', 'c']
리스트의 첫번째 값인 리스트의 첫번째 원소를 출력합니다.
>>> x[0][1]
'b'
리스트에 저장된 문자열의 앞뒤 공백을 제거합니다.
공백이 포함된 문자열 리스트를 생성합니다.
>>> string_list = [" hello ", " world ", " Python "]
리스트 내용을 확인해봅니다. 문자열에 공백이 추가되어 있는 것을 볼 수 있습니다.
>>> print(string_list)
[' hello ', ' world ', ' Python ']
리스트에 포함된 문자열의 앞뒤 공백을 제거합니다.
>>> trimmed_list = [s.strip() for s in string_list]
리스트 내용을 확인해보면, 문자열에 있던 공백이 제거된 것을 볼 수 있습니다.
>>> print(trimmed_list)
['hello', 'world', 'Python']
리스트의 append 메소드는 단일 요소를 리스트의 끝에 추가하고 리스트의 extend 메소드는 리스트의 모든 요소를 현재 리스트에 추가합니다.
# 초기 리스트 fruits = ['사과', '바나나'] # append 메소드를 사용하여 요소 하나를 리스트에 추가합니다. fruits.append('체리') print(fruits) # 출력: ['사과', '바나나', '체리'] # append 메소드를 사용하여 리스트를 리스트에 추가하면 리스트 전체가 원소로 추가됩니다. fruits.append(['오렌지', '포도']) print(fruits) # 출력: ['사과', '바나나', '체리', ['오렌지', '포도']] # 초기 리스트 fruits = ['사과', '바나나'] # extend 메소드를 사용하여 리스트를 리스트에 추가하면 두 리스트가 합쳐지는 결과를 얻을 수 있습니다. fruits.extend(['체리', '오렌지']) print(fruits) # 출력: ['사과', '바나나', '체리', '오렌지'] # extend 메소드를 사용하여 요소 하나를 추가하면 문자열이 문자 단위로 나누어져 리스트에 추가됩니다. fruits.extend('키위') print(fruits) # 출력: ['사과', '바나나', '체리', '오렌지', '키', '위'] |
extend 메소드를 사용하는 효과와 유사한것이 + 연산자를 사용하는 것입니다. 둘다 두 리스트가 합쳐지는 결과를 얻습니다. 차이는 extend 메소드는 원래 리스트를 직접 수정하며 + 연산자는 새로운 리스트를 생성하여 반환합니다. extend는 메모리 사용 측면에서 더 효율적일 수 있으며, 특히 대량의 데이터를 다룰 때 유용합니다. 반면, + 연산자는 새 리스트를 만들기 때문에 원본 리스트를 보존하고 싶을 때 유용합니다.
list1 = [1, 2, 3] list2 = [4, 5, 6] # extend 메소드 사용 list1.extend(list2) print(list1) # 출력: [1, 2, 3, 4, 5, 6] # + 연산자 사용 result = list1 + list2 print(result) # 출력: [1, 2, 3, 4, 5, 6] |
insert 메소드는 지정한 인덱스 위치에 원소를 삽입합니다.
list = [1, 2, 3, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 3, 4, 5] list.insert(0, 'a') print(list) # 리스트의 인덱스 0 위치에 문자 'a'를 삽입니다. 리스트 맨 앞에 삽입됩니다. # ['a', 1, 2, 3, 4, 5] list.insert(1, 'b') print(list) # 리스트의 인덱스 1 위치에 문자 'b'를 삽입니다. # ['a', 'b', 1, 2, 3, 4, 5] list.insert(len(list), 'c') print(list) # 리스트의 길이 만큼의 인덱스 위치, 즉 리스트 맨끝에 문자 'c'를 삽입합니다. list.append('c')와 동작이 동일합니다. # ['a', 'b', 1, 2, 3, 4, 5, 'c'] |
remove 메소드는 지정한 것을 리스트에서 찾아서 일치하는 첫번째 원소를 삭제합니다.
list = [1, 2, 1, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 1, 4, 5] list.remove(1) print(list) # remove에 지정한 것을 리스트에서 찾아서 일치하는 첫번째 원소가 삭제됩니다. # [2, 1, 4, 5] list.remove(10) # 리스트에 없는 원소를 삭제하려고 하면 ValeError가 발생합니다. # list.remove(10) # ValueError: list.remove(x): x not in list |
pop 메소드를 사용하면 지정한 인덱스에 있는 원소를 삭제하고 해당 원소를 리턴합니다.
list = [1, 2, 1, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 1, 4, 5] t = list.pop(1) print(t) print(list) # 지정한 인덱스 위치에 있는 원소를 리스트에서 제거하고 리턴해줍니다. 여기에선 2를 리턴하며 리스트에서 2가 삭제됩니다. # 2 # [1, 1, 4, 5] t = list.pop() print(t) print(list) # 인덱스를 지정하지 않으면 리스트 끝에 있는 원소를 제거하고 리턴해줍니다. 여기에선 5를 리턴하고 리스트에서 5가 삭제됩니다. # 5 # [1, 1, 4] t = list.pop(10) # 리스트에 없는 인덱스를 지정하면 IndexError가 발생합니다. # t = list.pop(10) # ^^^^^^^^^^^^ # IndexError: pop index out of range |
clear 메소드는 리스트의 모든 원소를 삭제합니다.
list = [1, 2, 1, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 1, 4, 5] list.clear() print(list) # 리스트의 모든 원소를 삭제합니다. 빈 리스트가 되기때문에 []가 출력됩니다. # [] |
index 메소드는 지정한 원소를 리스트에서 찾아서 해당 인덱스를 리턴합니다.
fruits = ['사과', '바나나', '오렌지', '배', '딸기', '오렌지'] print(fruits) # 원본 리스트입니다. # ['사과', '바나나', '오렌지', '배', '딸기', '오렌지'] # 인덱스 0 1 2 3 4 5 # '오렌지'의 인덱스를 찾습니다. orange_index = fruits.index('오렌지') print(orange_index) # 리스트에서 오렌지를 찾아서 해당하는 인덱스 2가 출력됩니다. # 2 # 리스트에 없는 원소를 찾으려고 시도하는 경우 ValueError 예외가 발생합니다. try: grape_index = fruits.index('포도') except ValueError: print("'포도'는 리스트에 없습니다.") # '포도'는 리스트에 없습니다. |
count 메소드는 지정한 원소의 개수를 리턴합니다.
list = [1, 2, 3, 1, 2, 1] print(list.count(1)) # 리스트에서 원소 1의 개수를 출력합니다. # 3 print(list.count(2)) # 리스트에서 원소 2의 개수를 출력합니다. # 2 |
sort 메소드는 리스트를 정렬합니다.
list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] print(list) # 원본 리스트입니다. # [3, 1, 4, 1, 5, 9, 2, 6, 5, 3] list.sort() print(list) # 오름차순으로 정렬합니다. # [1, 1, 2, 3, 3, 4, 5, 5, 6, 9] list.sort(reverse=True) print(list) # 내림차순으로 정렬합니다. # [9, 6, 5, 5, 4, 3, 3, 2, 1, 1] words = ['python', 'programming', 'language', 'code'] words.sort(key=len) print(words) # 문자열 길이를 기준으로 정렬합니다. # ['code', 'python', 'language', 'programming'] def get_last_letter(string): return string[-1] words.sort(key=get_last_letter) print(words) # 사용자 정의 함수에서 지정한 방식(마자막 글자)을 key로 사용하여 정렬합니다. # ['code', 'language', 'programming', 'python'] |
reverse 메소드는 리스트를 역순으로 정렬합니다.
list = [1, 2, 3, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 3, 4, 5] list.reverse() print(list) # 리스트를 역순으로 정렬합니다. # [5, 4, 3, 2, 1] |
copy 메소드는 리스트를 얕은 복사합니다.
list = [1, 2, 3, 4, 5] print(list) # 원본 리스트입니다. # [1, 2, 3, 4, 5] a = list.copy() # copy 메소드는 얕은 복사를 합니다. # 변수 a에도 리스트 list와 동일한 원소가 저장됩니다. print(a) # [1, 2, 3, 4, 5] list[0] = 'a' # 리스트 list의 첫번째 원소를 변경합니다. a[-1] = 'b' # 리스트 a의 마지막 원소를 변경합니다. print(list) print(a) # 얕은 복사 결과 list와 a의 원소 변경시 서로 영향을 주지 않습니다. # ['a', 2, 3, 4, 5] # [1, 2, 3, 4, 'b'] print(id(list)) print(id(a)) # id 함수는 변수가 가리키는 객체의 id를 리턴합니다. 변수 list와 변수 a가 가리키는 리스트가 서로다른 리스트 객체임을 알 수 있습니다. # 4347136320 # 4347442624 |
얕은 복사는 리스트 안에 리스트가 포함된 경우에는 문제가 될 수 있어 이때는 깊은 복사를 사용해야 합니다.
import copy list = [[1, 2], [3, 4]] print(list) # 원본 리스트입니다. # [[1, 2], [3, 4]] shallow_copy = list.copy() # 얕은 복사를 합니다. deep_copy = copy.deepcopy(list) # 갚은 복사를 합니다. # 원본 리스트의 중첩된 리스트를 수정합니다. list[1][0] = 99 print(list) # 원본 리스트의 두번쨰 원소에 있는 리스트의 첫번째 원소가 99로 변경되었습니다. # [[1, 2], [99, 4]] print(shallow_copy) # 얕은 복사를 한 경우에는 영향을 받습니다. # [[1, 2], [99, 4]] print(deep_copy) # 깉은 복사를 한 경우에는 영향을 받지 않습니다. # [[1, 2], [3, 4]] # 얕은 복사를 한 리스트의 중첩된 리스트를 수정합니다. shallow_copy[1][0] = 55 print(shallow_copy) # 얕은 복사를 한 리스트의 두번쨰 원소에 있는 리스트의 첫번째 원소가 55로 변경되었습니다. # [[1, 2], [55, 4]] print(list) # 원본 리스트는 영향을 받습니다. # [[1, 2], [55, 4]] print(deep_copy) # 깉은 복사를 한 경우에는 영향을 받지 않습니다. # [[1, 2], [3, 4]] # 깊은 복사를 한 리스트의 중첩된 리스트를 수정합니다. deep_copy[1][0] = 77 print(deep_copy) # 깊은 복사를 한 리스트의 두번쨰 원소에 있는 리스트의 첫번째 원소가 77로 변경되었습니다. # [[1, 2], [77, 4]] print(shallow_copy) # 얕은 복사를 한 리스트는 영향을 받지 않습니다. # [[1, 2], [55, 4]] print(list) # 원본 리스트는 영향을 받지 않습니다. # [[1, 2], [55, 4]] |
del 문을 사용하여 리스트의 하나의 원소 또는 슬라이스 또는 전체 원소를 제거할 수 있습니다.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9] print(a) # 원본 리스트입니다. # [1, 2, 3, 4, 5, 6, 7, 8, 9] del a[0] print(a) # 리스트의 첫번째 원소를 제거합니다. # [2, 3, 4, 5, 6, 7, 8, 9] del a[2:4] print(a) # 슬라이스를 지정하여 여러개의 원소를 제거합니다. # [2, 3, 6, 7, 8, 9] del a[:] print(a) # 리스트의 전체 원소를 제거합니다. # [] |
다음 포스트에 작성된 파이썬 강좌 링크들이 모아집니다.
누구나 다하는 파이썬 강좌
https://webnautes.tistory.com/2348