W systemie 64-bitowym liczba całkowita w Pythonie zajmuje 24 bajty. Jest to 3-krotność pamięci, która byłaby potrzebna w np. C dla 64-bitowej liczby całkowitej. Teraz wiem, że to dlatego, że liczby w języku Python są obiektami. Ale do czego służy dodatkowa pamięć? Mam swoje domysły, ale byłoby miło wiedzieć na pewno.Dlaczego ints wymagają trzy razy więcej pamięci w Pythonie?
Odpowiedz
Należy pamiętać, że typ Python int
nie ma ograniczonego zakresu, na przykład C int
; jedynym ograniczeniem jest dostępna pamięć.
Pamięć przechodzi do przechowywania wartości, bieżącego rozmiaru pamięci całkowitej (rozmiar pamięci jest zmienny, aby obsługiwać dowolne rozmiary), oraz standardowego przechowywania obiektów w języku Python (odniesienie do odpowiedniego obiektu i licznika odwołań).
Można wyszukać longintrepr.h
source (typ Python 3 int
był tradycyjnie znany jako typ long
w Pythonie 2); to sprawia, że efektywne wykorzystanie PyVarObject
C type śledzić całkowitą wielkość:
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
sklepach ob_digit
array „” z cyfr albo 15 lub 30 bitów szerokości (w zależności od platformy); tak na moim 64-bitowym systemie OS X, liczba całkowita do (2^30) - 1 używa 1 'cyfra':
>>> sys.getsizeof((1 << 30) - 1)
28
ale jeśli używasz 2 30-bitowych cyfr w liczbie dodatkowe 4 bajty są potrzebne, itp:
>>> sys.getsizeof(1 << 30)
32
>>> sys.getsizeof(1 << 60)
36
>>> sys.getsizeof(1 << 90)
40
podstawa 24 bajty są więc struktura PyObject_VAR_HEAD
, posiadających rozmiar obiektu, liczba odniesienia i wskaźnik typu (po 8 bajtów/64 bitów na moim 64-bitowe OS X platform) .
W Pythonie 2, całkowitymi < = sys.maxint
ale> = -sys.maxint - 1
są przechowywane przy użyciu simpler structure przechowującą tylko jedną wartość:
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
ponieważ wykorzystuje PyObject
zamiast PyVarObject
nie ma ob_size
pola w struktury i rozmiar pamięci jest ograniczony do 24 bajtów; 8 dla wartości long
, 8 dla licznika referencji i 8 dla wskaźnika obiektu typu.
W jaki sposób obsługiwane są wartości ujemne, jeśli int jest podane jako ciąg cyfr? Czy istnieje koncepcja dodatku dwóch w python? Jeśli wydrukuję szesnastkowo (-1) otrzymam -0x1 lub podobnie, jeśli wydrukuję bin (-1) otrzymam -0b1 Rozumiem, że to nie może być to, co jest reprezentowane wewnętrznie, jednak w jaki sposób python podejmuje decyzję, że jest to wartość ujemna czy wysoki bit nie jest ustawiony? – Har
@Har: rozmiar obiektu jest ustawiony na wartość ujemną. patrz [połączony plik nagłówka] (https://hg.python.org/cpython/file/5e303360db14/Include/longintrepr.h#l74) * Liczby ujemne są reprezentowane ob_size <0; *. Więc reprezentacja całkowita, która wymaga 2 wpisów 'ob_digits', wtedy' ob_size' ma wartość '2' lub' -2', druga sygnalizuje, że jest liczbą całkowitą ujemną. –
oznacza to, że nie jest to dwójkowe uzupełnienie, ale po prostu jest trochę w strukturze, co oznacza, czy jest ujemny czy nie? – Har
Z longintrepr.h widzimy, że 'int' Przedmiot pytona jest określona w tej konstrukcji C:
struct _longobject {
PyObject_VAR_HEAD
digit ob_digit[1];
};
cyfra jest 32-bitową wartością bez znaku. Większość miejsca zajmuje nagłówek obiektu o zmiennym rozmiarze. Od object.h, możemy znaleźć jego definicję:
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
Widzimy, że używamy Py_ssize_t, 64-bity zakładając systemu 64-bitowego do przechowywania rachubę „cyfry” w wartości. Jest to prawdopodobnie marnotrawstwo. Możemy również zobaczyć, że ogólny nagłówek obiektu ma 64-bitową liczbę odwołań oraz wskaźnik do typu obiektu, który również będzie 64-bitowym magazynem. Licznik odwołań jest konieczny, aby Python wiedział, kiedy zwolnić obiekt, a wskaźnik do typu obiektu jest konieczny, aby wiedzieć, że mamy int, a nie, powiedzmy, łańcuch, ponieważ struktury C nie mają możliwości przetestowania typu obiekt z dowolnego wskaźnika.
_PyObject_HEAD_EXTRA nie jest zdefiniowany w większości kompilacji Pythona, ale może być używany do przechowywania połączonej listy wszystkich obiektów Pythona na stercie, jeśli kompozycja włącza tę opcję, używając kolejnych dwóch wskaźników po 64 bity.
Zobacz ten artykuł: http://www.laurentluce.com/posts/python-integer-objects-implementation/ a także https://docs.python.org/2/c-api/structures.html do wspólnego struktury obiektowe w Pythonie – DNA
@DNA: mówi o podstawowym typie 'int' Pythona 2; typ 'long' w Pythonie 2 (zastępujący typ' int' w Pythonie 3) jest nieco bardziej skomplikowany. –
Należy zauważyć, że to pytanie i odpowiedzi są specyficzne dla implementacji referencyjnej CPython. Inne implementacje mogą mieć całkowicie inne zastosowanie pamięci (chociaż obowiązują te same ogólne zasady: rozmiar i inne metadane obiektu muszą być przechowywane). – Bob