Python/누구나 다하는 파이썬 강좌

누구나 다하는 파이썬 강좌 - 리스트(list)

webnautes 2024. 7. 21. 23:02
반응형

파이썬의 리스트에 대해 다루고 있습니다.



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





반응형