티스토리 뷰
파이썬 기본 자료 구조 : 배열
※ Python 배열(array,list) 의 기본 틀
설명 : 왼편에 변수명을 선언하고 대괄호 [] 안에 원소들을 넣어줍니다. 원소가 여러 개일 때, ,쉼표로 구분하여 표현해줍니다. 위의 리스트는 강원도, 경기도, 경상도, 전라도, 충청도 5개 원소로 구성되어 있습니다.
출처 : https://velog.io/@ybnr_92/Python-list
파이썬에서 배열은 list라고도 하는데 배열이란 여러 자료형들을 하나의 묶음으로 관리하고 각 원소간에는 순서(order)가 존재해서 인덱스(index)를 통해 접근이 가능한 자료형을 말합니다. 다시 말해서 배열 안에는 여러가지 자료형들이 들어갈 수 있으며, 그 원소 각각에는 순서가 있어 index를 통해 각 원소에 접근할 수 있습니다.
배열 즉 리스트는 정말 유용하고 많이 사용하며 기본적인 자료 구조이기 때문에 잘 활용할 수 있도록 합시다.😍
이제 배열에 있는 여러 operation들을 통해 공부해봅시다. 😊
1. 리스트 만들기
리스트를 사용하면 다양한 원소들의 모음을 만들 수 있습니다.
odd = [], add1 = list()
odd2 = [1,3,5,6,8]
odd3 = ["안녕", 1, 3, 5, [1,5], True]
odd4 = ["python", False, 1,3,5, [1,3,5]]
보시는 것과 같이 list를 선언만 할수도 있으며 list안에 한 원소로만 구성될수도 있고 다양한 원소로도 구성되어 있을 수 있습니다.
2. 리스트 인덱싱과 슬라이싱
list는 문자열처럼 인덱싱과 슬라이싱을 할 수 있는데 이때 인덱싱이라 함은 처음에 말한 것처럼 리스트에는 인덱싱이 붙어 있습니다.
odd = [1,2,3]
이 변수에서 첫 번째 원소는 1입니다. 그럼 이를 표현할 때에는
odd[0]
> 1
odd[-1]
> 3
이렇게 표현해줍니다. 언어마다 인덱싱의 시작번호가 다를 수 있는데 python에서는 첫 원소의 시작을 0으로 합니다. 또 마지막 원소를 가리킬 때는 -1 인덱스를 사용합니다.
odd[0] + odd[1]
> 3
이렇게 인덱싱을 통해 값에 접근하여 operation을 해줄 수 있습니다.
그럼 슬라이싱이란 무엇일까요?
표현 식 : 변수[start index, end index, interval]
odd[0:2]
> [1,2]
슬라이싱이란 본 뜻은 '나눈다'는 뜻입니다.
string = '1234'
string[1:3]
> '23'
string[:3]
> '123'
string[0:3:2]
> '13'
주의 😡
슬라이싱을 할 때 주의해야할 점은 마지막 인덱싱은 포함되지 않는다는 점입니다. 즉 지금 보시면 [1:3]까지 슬라이싱을 하지만 1,2 인덱스에 해당하는 값만 표현됩니다.
3. 리스트 연산하기
리스트는 +
와 *
연산을 할 수 있는데 살펴봅시다
a = [1,2]
b = [3,4]
a + b
> [1,2,3,4]
리스트를 더하게 되면 각 리스트의 원소들이 하나의 리스트로 결합되는 걸 볼 수 있습니다.*
연산을 한다면
a * 3
> [1,2,1,2,1,2]
*
연산은 해당 리스트의 원소들을 곱해준 수만큼 반복해서 한 리스트에 포함시킵니다.
주의 😡
다른 타입의 원소끼리 연산을 할 때 입니다.
a = [1,2,3,4,5]
a[0] + "안녕"
TypeError Traceback (most recent call last) in
1 a = [1,2,3]
----> 2 a[0] + "안녕"
3 a
TypeError: unsupported operand type(s) for +: 'int' and 'str'
이건 꼭 리스트에서 뿐만이 아니라 모든 연산에서 적용되는 것이므로 조심합니다.
3-1. 리스트 파악하기
1) 리스트 길이 구하기
리스트의 길이를 구할 때는 len()
이라는 코드를 씁니다.
a = [1,2,3]
len(a)
> 3
2) 리스트 원소 수정하기
리스트의 각 원소를 인덱스로 접근하여 해당 인덱스의 원소값을 수정할 수 있습니다.
a = [1,2,3,4]
a[0] = 10
a
> [10,2,3,4]
3) 리스트 원소 추가하기
해당 리스트에 자신이 원하는 원소를 추가할 수 있습니다. 이때 두 가지 방법이 있는데 하나는 append()
입니다.
a = [1,2,3]
a.append(4)
a
> [1,2,3,4]
append()
라는 기능을 이용하면 해당 리스트에 원하는 원소를 뒤로 추가 시킵니다. 이때 원소의 타입은 다양하게 할 수 있습니다.
다른 방법은 insert()
기능을 사용하는 것입니다.
a = [1,2,3]
a.insert(0,4)
a
> [4,1,2,3]
insert()
함수는 append()
와 달리 원하는 인덱스 자리에 원하는 원소를 추가할 수 있습니다.
4) 리스트에서 원소 삭제하기(del
,clear
,remove()
)
python 에서 자체적으로 가지고 있는 기능인 del
을 사용하여 리스트에서 원하는 원소를 삭제할 수 있습니다.
a = [1,2,3]
del a[0]
a
> [2,3]
a = [1,2,3,4,5]
del a[:3]
a
> [5]
del
기능을 사용하면 원하는 인덱스의 원소 값이 삭제됩니다. 또 여러 값도 동시에 제거할 수 있습니다.
clear()
함수는 모든 원소를 제거 할 수 있습니다. 기능적으로 del a[:]
와 동일합니다.
a = [1,2,3]
a.clear()
a
> []
또 remove()
함수를 이용하여 리스트 원소 값을 제거 할 수 있습니다.
a = [1,2,3,4,1]
a.remove(1)
a
> [2,3,4,1]
a.remove(1)
a
> [2,3,4]
이때 주의할 점은 remove
함수에는 원소 값을 넣어야 합니다. 인덱스 값을 넣는 것이 아닙니다. 또한 처음 나온 원소값 하나만을 제거해주기 때문에 주의합니다.
5) 리스트 원소 값 정렬하기(sort
, sorted
의 차이 구분)
sort()
함수를 사용하여 리스트의 원소 값들을 내림차순, 오름차순으로 정렬을 할 수 있습니다.
a = [1,4,2,3]
a.sort()
a
> [1,2,3,4] # a 변수 원소 값이 정렬되었다.
주의 😡
sort()
를 사용하면 해당 리스트 변수의 원래 값에 적용되기 때문에 이를 인지하여 사용하여야 합니다. 반면 sorted()
라는 함수를 사용하면 해당 리스트의 값은 변하지 않지만, 정렬기능이 이루어졌을 때의 원소 값이 출력됩니다.
a = [1,5,3,2,4]
sorted(a)
>[1,2,3,4,5] # a 변수의 원소 값만 가지고 사용
a
> [1,5,3,2,4] # a 변수의 값은 그대로이다.
저는 이를 어떻게 구분하냐면, sort()
는 a.sort()
라고 쓰이고, sorted()
는 sorted(a)
라고 사용됩니다 sort
는 a라는 리스트에 접근하여 그 변수의 값을 정렬한다고 보고, sorted()
는 a의 변수에 접근하는 것이 아니라 a의 데이터를 사용하여 그 값만 사용한다고 인식합니다.
sort()
함수는 기본적으로 오름차순으로 정해있지만 내림차순으로 사용할수도 있습니다.
a = [1,5,3,2,4]
a.sort(reverse=True)
a
> [5,4,3,2,1]
Default 값은 sort(reverse=False)
이기 때문에 오름차순으로 나온 것입니다.
6) 리스트 뒤집기(reverse()
, reversed()
)
정렬을 시키는 sort()
에서 사용하는 reverse 변수는 내림차순으로 바꾸어주는 것이고, 여기서 사용하는 reverse
, reversed
함수는 리스트를 뒤집는 것이므로 주의합니다.
a = [1,4,2,3]
a.reverse()
a
> [3,2,4,1]
결과를 보시면 리스트값이 반대로 된 것을 알 수 있습니다. 내림정렬이 아닙니다!!!
a = [1,4,2,3]
reversed(a)
<list_reverseiterator at 0x14d6a5c2808>
reversed()
함수는 값을 반환하긴 하지만 list_reverseiterator
라는 객체를 반환합니다. 그래서 이를 다시 출력하기 위해서는 list()
를 사용해야합니다
list(reversed(a))
> [3,2,4,1]
a
> [1,4,2,3]
위에서 봤던 sort()
와 sorted()
의 차이와 같이 reversed()
는 원 변수의 값은 변하지 않지만 그 원소값들만을 사용하여 변한 값을 반환해줍니다.
7) 리스트 위치 반환하기(index()
)
리스트는 인덱싱을 할 수 있다고 했습니다. a[0]
이런 식으로 a 변수의 첫 번째 값에 접근할 수 있는데 반대로 내가 원하는 원소값이 어느 위치에 있는지를 알고 싶을 때가 있습니다. 이때 사용하는 함수가 index()
함수입니다.
a = [10,20,30]
a.index(10)
> 0
index()
함수를 사용하여 10
이라는 원소 값이 0번인덱스에 있다고 나옵니다.
만약 없는 원소 값을 넣으면 어떻게 될까요?
a = [10,20,30]
a.index(40)
ValueError Traceback (most recent call last) in
1 a = [10,20,30]
----> 2 a.index(40)
ValueError: 40 is not in list
8) 리스트 원소 값 꺼내기(pop()
)
pop()
함수는 말 그대로 "꺼내다"는 의미를 가지고 있습니다. 꺼내진 값을 사용할 수 있으며, pop()
으로 꺼내진 값은 해당 리스트의 값에서 삭제됩니다.
python 자료구조와 알고리즘을 공부하다 보면 빈번하게 선입선출 FIFO(First In, First Out) 와 후입선출LIFO(Last In, First Out) 라는 단어를 들어볼 수 있는데 이를 리스트 자료구조와 pop()
함수 를 사용하여 간편하게 작업할 수 있습니다.
a = [1,2,3,4]
a.pop()
>
a
> [1,2,3]
기본적으로 pop을 사용하면 LIFO, 즉 마지막 들어온 것을 먼저 꺼냅니다. 이는 바닥이 막혀있고 위는 열린 스택구조와도 동일한 기능을 합니다.
a = [1,2,3,4]
a.pop(0)
> 1
a
> [2,3,4]
반대로 FIFO의 구조를 가지고 싶다면 pop()
에 첫 인덱스 값을 넣어주기만 하면 됩니다.
9) 리스트 원하는 원소 수 세기( count()
)
count()
함수를 사용하여 리스트에서 자신이 원하는 원소의 수를 셀 수 있습니다.
a = [1,4,5,4,2,4]
a.count(4)
> 3
10) 리스트 확장하기 ( extend()
)
extend()
함수를 사용하여 리스트와 리스트를 합칠 수 있습니다.
a = [1,2,3]
b = [4,5,6]
a.extend(b)
a
> [1,2,3,4,5,6]
extend()
함수는 리스트와 리스트를 합치는 것으로 a + b
와 동일한 기능을 수행합니다.
11) 리스트 복사하기 ( copy()
)
우선 복사의 개념을 살펴보면 두 가지 경우가 있습니다. 하나는 얕은 복사(shallow copy)
, 다른 하나는 깊은 복사(deep copy)
입니다. 얕은 복사
를 알아봅시다.
a = [1,2,3]
b = a
id(a)
> 1432003006152
id(b)
> 1432003006152
a == b
> True
a is b
> True
b[0] = 10
b
> [10,2,3]
a
> [10,2,3]
보시면, a의 아이디와 b의 아이디가 같습니다. a와 b의 원소가 같은가를 물어보면 True
값을 반환하고 a가 b인가를 물어보면 True
반환합니다. 즉 a와 b의 아이디가 같고 b를 바꾸면 a도 바뀝니다. import copy
에서 copy
는 얕은 복사
를 의미하기 때문에 b.copy.copy(a)
기능을 사용해서 얕은 복사
를 할 수 있습니다
우리가 생각할 때 copy는 다른 변수에 같은 원소 값만을 넣고 싶은데 이를 깊은 복사
라고 합니다.깊은 복사
는 얕은 복사
와 다르게 다른 주소를 가지는 변수에다가 같은 데이터를 넣는 것입니다.
import copy
a = [1,2,3]
b = copy.deepcopy(a)
id(a)
> 1432011675080
id(b)
> 1432011673864
a == b
> True
a is b
> False
b[0] = 10
b
> [10,2,3]
a
> [1,2,3]
살펴보면 a
와 b
의 값은 같지만 a
가 b
라는 건 아닙니다. 또한 b
의 값을 바꿨을 때 a
에 영향을 받지 않는 걸 볼 수 있습니다.
12) 리스트 컴프리헨션
리스트를 선언할 때 아래와 같이 선언합니다.
a = [] or a = list()
sq = []
for x in range(10):
sq.append(x**2)
sq
>[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
그러나 만약에 엄청 큰 숫자의 배열을 리스트에 담을 때는 하나하나 담거나 반복문(for
,while
)을 사용하여 포함시킵니다. 이를 좀 더 간편하게 해주는 python 기능이 있는데 이를 컴프리헨션이라고 합니다.
sq = [x**2 for x in range(10)] or sq = list(map(lambda x: x**2, range(10)))
좀 더 발전시켜서 반복문과 조건문(if
)을 사용하여 만들수도 있습니다.
[(x,y) for x in [1,2,3] for y in [4,5,6] if x != y ]
>[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
12-1) 중첩 컴프리헨션
행렬을 전치할 때 중첩된 컴프리헨션을 사용하는 예를 살펴보겠습니다.
matrix = [
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
]
[[row[i] for row in matrix] for i in range(4)]
>[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
이렇게 컴프리헨션에 적응하면 적은 코드수로 동일한 효과를 낼 수 있기 때문에 연습하면 유용합니다.
지금까지 리스트, 배열의 기본적인 기능을 알아봤습니다.
리스트를 활용하여 여러 자료구조를 구현할 수 있습니다. 다음 시간에는 리스트를 활용하여 스택(stack)과 큐(queue) 자료구조를 구현해봅시다.
많이 딱딱할 수 있지만, 이 문법들을 가지고 어떤 기능들을 수행할 수 있는 도구로 사용한다면 정말 아름답고 흥미롭게 공부하실 수 있습니다. 긴 글 읽어주셔서 감사드립니다. 😆
참고 :
- 점프 투 파이썬 (리스트부분)
- 패스트캠프 강의자료
- Python 공식 document
- 파이썬 - 기본을 갈고 닦자!