00 개요
- 파이썬 리스트를 생성하는 PyList_New() 함수에 대한 정리
- 코드 분석 중 PyList_New() 함수는, 인자로 생성될 list의 크기를 줘야만 하는 함수인 줄 알았는데 PyObject *result = PyList_New(0)으로 선언한 뒤 result에 값이 추가가 되는 것을 보고 멘붕와서 이에 대한 설명을 하고자 함
- 요약: PyObject* myList = PyList_New(0); 실행 시
- myList는 초기 크기가 0인 빈 Python 리스트로 생성됨
- 이 리스트는 처음에는 요소를 포함하지 않지만, 이후에 요소 추가될 수 있음
- Python의 리스트는 동적으로 크기 조정이 가능하기에, 처음에 크기가 0이어도 나중에 항목 추가 가능'
01 PyList_New(size) 함수
1. 정의
- Python C API에서 제공되는 함수로, Python 리스트 객체 생성 시 사용됨
2. 문법
PyObject* PyList_New(Py_ssize_t size);
- 입력 인자: size
- 리스트의 초기 크기
- Py_ssize_t는 signed size 타입으로, 리스트의 길이를 지정
- 즉, 리스트에 포함될 요소의 수를 나타냄
- 반환 값: PyObject*
- 생성된 Python 리스트 객체를 가리키는 포인터
- 만약 메모리 할당에 실패하면 NULL을 반환
3. 동작 원리
1) 초기화:
- PyList_New(size)는 주어진 size 크기를 가지는 새로운 리스트를 생성
- 생성된 리스트는 초기화되어 있으며, 리스트의 각 요소는 NULL로 초기화 됨
2) 리스트 요소 초기화
- 생성된 리스트의 크기는 size로 지정되지만, 리스트의 모든 요소는 아직 값이 할당되지 않아있는 상태
- 각 요소는 NULL 포인터를 가짐
- 즉, 리스트의 요소를 사용하기 전에 각각의 위치에 값을 할당해주어야 함
3) 메모리 관리
- 리스트가 생성되면, Python의 메모리 관리 시스템에 의해 관리됨
- 이는 garbage collection에 의해 처리됨
- 리스트가 더 이상 사용되지 않으면 메모리가 자동으로 해제됨
4. 예시
PyObject* myList = PyList_New(3); // 크기가 3인 리스트 생성
if (!myList) { // 메모리 할당 실패 시 처리
return NULL;
}
// 각 리스트 요소에 값을 할당
PyList_SetItem(myList, 0, PyLong_FromLong(10)); // 첫 번째 요소에 10 추가
PyList_SetItem(myList, 1, PyLong_FromLong(20)); // 두 번째 요소에 20 추가
PyList_SetItem(myList, 2, PyLong_FromLong(30)); // 세 번째 요소에 30 추가
- 설명:
- 리스트 생성:
- PyList_New(3)은 크기가 3인 리스트를 생성
- 이 리스트는 [NULL, NULL, NULL]로 초기화됨
- 요소 추가:
- PyList_SetItem을 사용하여 리스트의 각 요소에 값을 할당
- 이제 리스트는 [10, 20, 30]의 값을 가짐
- 리스트 생성:
- 중요한 주의사항
- 초기화 후 요소 설정:
- 리스트가 생성된 후, PyList_SetItem 또는 PyList_Append 등을 사용하여 리스트의 각 요소를 설정 필수
- 초기화되지 않은 NULL 포인터가 남아 있으면, 잘못된 메모리 접근이나 프로그램 충돌이 발생 가능
- 참조 카운트:
- PyList_SetItem은 해당 위치의 기존 항목을 제거하고 새 항목을 삽입함
- 이 과정에서 새로 삽입된 객체의 참조 카운트를 증가시키지 않음
- 이는 성능 최적화를 위해서이며, 이로 인해 참조 카운트 관리에 주의 필요 - 추후에 더 알아보기
- 초기화 후 요소 설정:
5. 요약
- PyList_New(size)는 size 크기의 리스트를 생성하지만, 초기화된 상태에서는 리스트의 요소가 NULL로 설정됨
- 이 함수로 생성된 리스트에 값을 추가하려면, PyList_SetItem 등을 사용해야 하며, 이를 통해 요소를 적절하게 설정 가능
- Python의 리스트는 동적 배열로, 초기 크기를 설정한 후에도 동적으로 크기를 조정 가능하기에 처음에 크기가 0인 PyList_New(0)으로 리스트를 만들어도 나중에 이 리스트에 값을 추가할 수 있는 것!
02 Python 리스트의 동적 크기 조정
- Python의 리스트는 동적 배열(dynamic array)
- 리스트의 크기는 초기화 시에 정해지더라도, PyList_Append와 같은 함수를 사용해 리스트에 항목을 추가 가능
- 이 과정에서 리스트의 내부 배열이 자동으로 확장
1. 예시
PyObject* myList = PyList_New(0); // 빈 리스트 생성 (크기 0)
PyObject* item = PyLong_FromLong(42);
PyList_Append(myList, item); // 리스트에 42 추가 (크기 1로 증가)
- 초기화:
- PyList_New(0)은 크기가 0인 빈 리스트 생성
- 리스트에는 아직 요소가 없지만, 추가할 준비는 되어 있는 상태
- 동적 확장:
- PyList_Append(myList, item) 호출 시 Python 내부에서 리스트의 크기를 동적으로 조정하여 새로운 항목을 추가
- 예시 설명:
- 처음: myList는 빈 리스트
- PyList_Append 호출 후: 리스트에 42가 추가되고, 리스트의 크기는 1이 됨
2. PyList_New(size)의 의미
- PyList_New(0): 빈 리스트 생성. 리스트의 초기 크기는 0
- 이후 PyList_Append 등을 통해 항목을 추가하면 크기가 자동으로 늘어남
- PyList_New(size): 주어진 size만큼의 크기를 가지는 리스트 생성. 리스트는 size만큼의 공간을 예약하지만, 해당 공간은 NULL 포인터로 초기화됨
- 리스트의 각 요소에 값이 할당되지 않으면, NULL 포인터로 남아 있음
3. 요약
- PyList_New(0)은 크기가 0인 리스트를 생성하지만, Python의 리스트는 동적으로 크기를 조정할 수 있으므로 이후에 값이 추가될 수 있음
- PyList_Append는 리스트에 값을 추가할 때, 리스트가 필요에 따라 크기를 자동으로 늘림
- 따라서, 리스트의 초기 크기와 관계없이 항목을 자유롭게 추가 가능!
'C' 카테고리의 다른 글
Python으로 데이터 전달 - sizeof()와 strlen()로 안전한 메모리 관리 (0) | 2024.09.02 |
---|---|
구조체의 필드에 접근 방법 (->, .) (0) | 2024.08.30 |
memset (C 메모리 초기화 함수) (0) | 2024.08.28 |
struct 구조체 (C언어 데이터 타입) (0) | 2024.08.09 |
매크로 함수, 인라인 함수(#define, #inline) (0) | 2024.06.25 |