[의문 해결]파이썬 배열과 NumPy배열의 차이 알아보기(파이썬 배열 분석)

OasisGorilla·2024년 10월 1일
0

행렬 텐서 공부중에 gpt가 다음과 같이 대답을 하는 것을 봤다.

차이점 요약:

리스트: X[행][열]처럼 두 번 접근.
NumPy 배열: X[행, 열]처럼 한 번에 접근.

파이썬 리스트와 NumPy로 만든 배열의 차이점을 물어봤을 때 내놓은 대답이었다.

먼저 리스트(list)와 배열(array)는 엄연히 다른 개념으로 쓰인다는 것을 짚고 넘어가야 한다.

대부분의 프로그래밍 언어에서 말하는 배열과 리스트는 다음과 같다.

  • 배열(array)
    인덱스와 인덱스에 대응하는 데이터들로 이루어진 자료 구조,
    일반적으로 정해진 공간 내에서 같은 종류의 데이터들이 순차적으로 저장됨

  • 연결리스트(linked list)
    각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 자료구조,
    포인터가 다음이나 이전 노드를 가리키며, 노드를 동적으로 이어붙일 수 있음
    [출처, 위키백과]

위 보기에서 가장 눈에 띄는 차이점은 인덱스의 유무이다. 그리고 구현된 방식도 다르다.
연결 리스트는 중간에 끼워넣기를 하려면 끼워넣으려는 곳의 앞노드의 포인터만 수정해주면 된다.
그러나 배열은 이미 인덱스마다 데이터가 짝지어져 있기 때문에 끼워넣으려는 데이터 이후의 인덱스-데이터 쌍을 모두 수정해줘야 한다.

파이썬의 리스트는 위 둘 중에 어느곳에도 속하지 않는다.
최대한 쓰기 편하게 두 자료구조의 특징들을 합쳐놓은 새로운 자료구조이다.

  1. 크기를 미리 정해놓고 사용하지 않아도 됨(연결리스트의 장점)
  2. 다양한 타입의 데이터를 섞어서 저장할 수 있음(연결리스트의 장점)
  3. 인덱스를 사용하여 데이터에 접근할 수 있음(배열의 장점)

첫번째 특징이 가능한 이유는
파이썬 리스트가 동적 배열로 구현되어있기 때문이다.

동적 배열(Dynamic array)
연속적인 메모리 공간에 데이터를 저장하지만 크기가 고정되어 있지 않음
공간이 꽉차면 더 큰 메모리 공간을 할당하고 기존 데이터를 복사해서 옮김

기존 배열은 미리 정해진 크기에 맞춰 사용해야하지만, 파이썬 배열은 크기가 동적으로 바뀐다.

두번째 특징은 파이썬 리스트 자료구조의 특징이라기 보다는 파이썬이기 때문에 가능한 특징이다.

먼저 기존 c나 java의 배열이 동일한 타입만 저장할 수 있는 이유는 인덱싱을 하려면 연속적인 메모리 공간 안에서 해당 인덱스의 시작 주소를 유추할 수 있어야 한다.
이때 데이터 타입이 같으면 정해진 공간을 데이터 타입 크기대로 일정하게 나눠서 인덱스의 시작 주소를 유추할 수 있다.

연속된 10의 공간에 공간을 1차지하는 데이터가 7개 저장돼있다고 하면, 포인터에 1씩 더해서 각각의 데이터가 어디 포인터에 저장되어 있는지 알 수 있지 않는가?
데이터의 타입이 다르면 차지하는 공간도 달라지고 데이터가 저장된 포인터를 유추하기가 참 어려워진다.

그러면 파이썬은 왜 여러가지 데이터를 배열에 넣을 수 있을까?

파이썬의 모든 데이터 타입은 객체로 간주된다.
x = 5 와 같이 변수를 정의해도 5가 스택에 있는 x에 담긴 것이 아니라, 5가 있는 힙 메모리 주소가 x에 담긴 것이다.
y = 5 를 할 경우 y에도 똑같은 메모리 주소가 담겨서 y가 힙에 생긴 5를 참조하게 된다.
리스트 안에 각각의 공간에는 값이 아닌, 포인터(메모리 주소)가 담긴다. 타입이 포인터로 통일된 것이다.
파이썬 리스트는 연속된 공간에 각각 다른 타입 데이터의 포인터를 담았기 때문에 다양한 데이터를 섞어서 사용할 수 있는것이다.

세번째는 위 설명들로 알 수 있다. 동적배열이기 때문에 연속된 공간에 생성되고, 이 덕분에 인덱싱을 할 수 있는 것이다.

여기까지가 파이썬 리스트이다.

2편에서 NumPy 배열에 대해서 알아보겠다.

0개의 댓글