두 개의 동일한 목록에 다른 메모리 공간이있는 이유는 무엇입니까?
나는이 목록을 작성 l1
하고 l2
있지만, 다른 생성 방법과 각각 :
import sys
l1 = [None] * 10
l2 = [None for _ in range(10)]
print('Size of l1 =', sys.getsizeof(l1))
print('Size of l2 =', sys.getsizeof(l2))
그러나 결과는 나를 놀라게했습니다.
Size of l1 = 144
Size of l2 = 192
리스트 이해력으로 생성 된리스트는 메모리에서 더 큰 크기이지만, 그렇지 않으면 파이썬에서 두리스트는 동일합니다.
왜 그런 겁니까? 이것이 CPython 내부적 인 것입니까, 아니면 다른 설명입니까?
을 쓸 때 [None] * 10
Python은 정확히 10 개의 객체 목록이 필요하다는 것을 알고 있으므로 정확히 할당합니다.
리스트 이해를 사용할 때, 파이썬은 그것이 얼마나 필요한지 알지 못합니다. 따라서 요소가 추가됨에 따라 목록이 점차 커집니다. 각 재 할당마다 즉시 필요한 것보다 많은 공간을 할당하므로 각 요소에 대해 재 할당 할 필요가 없습니다. 결과 목록은 필요한 것보다 다소 클 수 있습니다.
비슷한 크기로 작성된 목록을 비교할 때이 동작을 볼 수 있습니다.
>>> sys.getsizeof([None]*15)
184
>>> sys.getsizeof([None]*16)
192
>>> sys.getsizeof([None for _ in range(15)])
192
>>> sys.getsizeof([None for _ in range(16)])
192
>>> sys.getsizeof([None for _ in range(17)])
264
첫 번째 방법은 필요한 것만 할당하고 두 번째 방법은 주기적으로 자라는 것을 알 수 있습니다. 이 예에서는 16 개의 요소에 충분히 할당되었으며 17 일에 다시 할당해야했습니다.
이 질문 에서 언급했듯이 목록 이해력은 list.append
후드에서 사용하므로 전체적으로 할당되는 목록 크기 조정 메소드를 호출합니다.
이것을 직접 보여주기 위해 실제로 dis
dissasembler를 사용할 수 있습니다 :
>>> code = compile('[x for x in iterable]', '', 'eval')
>>> import dis
>>> dis.dis(code)
1 0 LOAD_CONST 0 (<code object <listcomp> at 0x10560b810, file "", line 1>)
2 LOAD_CONST 1 ('<listcomp>')
4 MAKE_FUNCTION 0
6 LOAD_NAME 0 (iterable)
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x10560b810, file "", line 1>:
1 0 BUILD_LIST 0
2 LOAD_FAST 0 (.0)
>> 4 FOR_ITER 8 (to 14)
6 STORE_FAST 1 (x)
8 LOAD_FAST 1 (x)
10 LIST_APPEND 2
12 JUMP_ABSOLUTE 4
>> 14 RETURN_VALUE
>>>
코드 객체 LIST_APPEND
의 디스 어셈블리 에서 opcode를 확인하십시오 <listcomp>
. 로부터 문서 :
LIST_APPEND (i)
전화
list.append(TOS[-i], TOS)
. 목록 이해를 구현하는 데 사용됩니다.
이제리스트 반복 작업의 경우 다음을 고려할 때 진행중인 작업에 대한 힌트가 있습니다.
>>> import sys
>>> sys.getsizeof([])
64
>>> 8*10
80
>>> 64 + 80
144
>>> sys.getsizeof([None]*10)
144
So, it seems to be able to exactly allocate the size. Looking at the source code, we see this is exactly what happens:
static PyObject *
list_repeat(PyListObject *a, Py_ssize_t n)
{
Py_ssize_t i, j;
Py_ssize_t size;
PyListObject *np;
PyObject **p, **items;
PyObject *elem;
if (n < 0)
n = 0;
if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n)
return PyErr_NoMemory();
size = Py_SIZE(a) * n;
if (size == 0)
return PyList_New(0);
np = (PyListObject *) PyList_New(size);
Namely, here: size = Py_SIZE(a) * n;
. The rest of the functions simply fills the array.
None is a block of memory, but it is not a pre-specified size. In addition to that, there is some extra spacing in an array between array elements. You can see this yourself by running:
for ele in l2:
print(sys.getsizeof(ele))
>>>>16
16
16
16
16
16
16
16
16
16
Which does not total the size of l2, but rather is less.
print(sys.getsizeof([None]))
72
And this is much greater than one tenth of the size of l1
.
Your numbers should vary depending on both the details of your operating system and the details of current memory usage in your operating system. The size of [None] can never be bigger than the available adjacent memory where the variable is set to be stored, and the variable may have to be moved if it is later dynamically allocated to be larger.
'IT story' 카테고리의 다른 글
R 함수에서 선택적 인수를 지정하는 "올바른"방법 (0) | 2020.06.15 |
---|---|
익명 유형을 가진 LINQ Select Distinct (0) | 2020.06.15 |
HTML5에서 RTSP 또는 RTP를 통한 스트리밍 (0) | 2020.06.15 |
URL에서 프로토콜을 상속하기 위해 선행 이중 슬래시를 사용하는 데 단점이 있습니까? (0) | 2020.06.15 |
Chrome 브라우저 새로 고침 옵션 새로운 기능 (0) | 2020.06.15 |