Python 목록 대상 실현 원리 상세 설명
typedef struct {
#
int ob_refcnt;
#
struct _typeobject *ob_type;
#
int ob_size; /* Number of items in variable part */
# ,list[0] ob_item[0]
PyObject **ob_item;
#
Py_ssize_t allocated;
} PyListObject;
어떻게 보면 PyListObject 대상 의 정 의 는 매우 간단 합 니 다.통용 대상 을 제외 하고 모두 있 는 인용 계수(obrefcnt),유형 정보(obtype),그리고 길 어 지 는 대상 의 길이(obsize)외 에 남 은 것 은 obitem,allocated,obitem 은 목록 요소 용 기 를 진정 으로 저장 하 는 지침 입 니 다.목록 요 소 를 저장 하 는 메모리 가 있 습 니 다.이 메모리 의 크기 는 allocated 가 수용 할 수 있 는 공간 입 니 다.allocated 는 목록 에 수용 할 수 있 는 요소 크기 이 며 조건 을 만족 시 킵 니 다.목록 개체 생 성
PylistObject 대상 은 함수 로 PyListNew 생 성,수신 매개 변수 size,이 매개 변 수 는 목록 대상 이 수용 할 수 있 는 최대 요소 개 수 를 지정 하 는 데 사 용 됩 니 다.
// , PyList_MAXFREELIST 80
static PyListObject *free_list[PyList_MAXFREELIST];
//
static int numfree = 0;
PyObject *PyList_New(Py_ssize_t size)
{
PyListObject *op; //
size_t nbytes; //
if (size < 0) {
PyErr_BadInternalCall();
return NULL;
}
/* Check for overflow without an actual overflow,
* which can cause compiler to optimise out */
if ((size_t)size > PY_SIZE_MAX / sizeof(PyObject *))
return PyErr_NoMemory();
nbytes = size * sizeof(PyObject *);
if (numfree) {
numfree--;
op = free_list[numfree];
_Py_NewReference((PyObject *)op);
} else {
op = PyObject_GC_New(PyListObject, &PyList_Type);
if (op == NULL)
return NULL;
}
if (size <= 0)
op->ob_item = NULL;
else {
op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
if (op->ob_item == NULL) {
Py_DECREF(op);
return PyErr_NoMemory();
}
memset(op->ob_item, 0, nbytes);
}
# ob_size
Py_SIZE(op) = size;
op->allocated = size;
_PyObject_GC_TRACK(op);
return (PyObject *) op;
}
생 성 과정 은 다음 과 같 습 니 다:free_list 는 PyListObject 대상 의 버퍼 입 니 다.크기 는 80 입 니 다.그러면 PyListObject 대상 은 언제 버퍼 에 가입 합 니까 free리스트 는 요?정 답 은 listdealloc 방법 중:
static void
list_dealloc(PyListObject *op)
{
Py_ssize_t i;
PyObject_GC_UnTrack(op);
Py_TRASHCAN_SAFE_BEGIN(op)
if (
i = Py_SIZE(op);
while (--i >= 0) {
Py_XDECREF(op->ob_item[i]);
}
PyMem_FREE(op->ob_item);
}
if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
free_list[numfree++] = op;
else
Py_TYPE(op)->tp_free((PyObject *)op);
Py_TRASHCAN_SAFE_END(op)
}
PyListObject 대상 이 소각 되 었 을 때 목록 에 있 는 모든 요소 의 인용 수 를 1 로 줄 인 다음 ob 를 방출 합 니 다.item 이 사용 하 는 메모리 입 니 다.버퍼 공간 이 채 워 지지 않 았 다 면 이 PyListObject 를 버퍼 에 추가 하 십시오.(이때 PyListObject 가 사용 하 는 메모리 가 시스템 에 진정 으로 회수 되 지 않 습 니 다.다음 에 PyListObject 를 만 들 려 면 버퍼 에서 PyListObject 를 우선 가 져 옵 니 다.)그렇지 않 으 면 PyListObject 대상 의 메모리 공간 을 풀 어 줍 니 다.목록 요소 삽입
목록 의 특정한 위치의 값 을 설정 할 때"list[1]=0"과 같이 목록 의 메모리 구 조 는 변 하지 않 고 목록 에 요 소 를 삽입 할 때 목록 의 메모리 구 조 를 바 꿉 니 다.
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
// n
Py_ssize_t i, n = Py_SIZE(self);
PyObject **items;
if (v == NULL) {
PyErr_BadInternalCall();
return -1;
}
if (n == PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to list");
return -1;
}
if (list_resize(self, n+1) == -1)
return -1;
if (where < 0) {
where += n;
if (where < 0)
where = 0;
}
if (where > n)
where = n;
items = self->ob_item;
for (i = n; --i >= where; )
items[i+1] = items[i];
Py_INCREF(v);
items[where] = v;
return 0;
}
목록 위 치 를 설정 하 는 값 보다 삽입 작업 이 PyListObject 용량 크기 를 한 번 더 조정 해 야 합 니 다.논 리 는 list 입 니 다.resize,그 다음은 where 이후 의 요소 위 치 를 옮 기 는 것 입 니 다.
// newsize:
static int
list_resize(PyListObject *self, Py_ssize_t newsize)
{
PyObject **items;
size_t new_allocated;
Py_ssize_t allocated = self->allocated;
if (allocated >= newsize && newsize >= (allocated >> 1)) {
assert(self->ob_item != NULL || newsize == 0);
Py_SIZE(self) = newsize;
return 0;
}
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
/* check for integer overflow */
if (new_allocated > PY_SIZE_MAX - newsize) {
PyErr_NoMemory();
return -1;
} else {
new_allocated += newsize;
}
if (newsize == 0)
new_allocated = 0;
items = self->ob_item;
if (new_allocated <= (PY_SIZE_MAX / sizeof(PyObject *)))
PyMem_RESIZE(items, PyObject *, new_allocated);
else
items = NULL;
if (items == NULL) {
PyErr_NoMemory();
return -1;
}
self->ob_item = items;
Py_SIZE(self) = newsize;
self->allocated = new_allocated;
return 0;
}
allocated>=newsize&&newsize>=(allocated/2)을 만족 시 킬 때 list 의 요소 길 이 를 간단하게 바 꾸 면 PyListObject 대상 은 메모리 공간 을 재배 치 하지 않 고 메모리 공간 을 재배 치 합 니 다.만약 newsize총결산
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.