tipos str numeros letras imprimir entrada datos convertir concatenar python python-3.x int python-internals

str - Comprender la asignación de memoria para enteros grandes en Python



str en python (2)

¿Cómo asigna Python la memoria para enteros grandes?

Un tipo int tiene un tamaño de 28 bytes y a medida que sigo aumentando el valor de int , el tamaño aumenta en incrementos de 4 bytes .

  1. ¿Por qué 28 bytes inicialmente para cualquier valor tan bajo como 1 ?

  2. ¿Por qué incrementos de 4 bytes ?

PD: estoy ejecutando Python 3.5.2 en una x86_64 (máquina de 64 bits). Cualquier puntero / recurso / PEP sobre cómo los intérpretes (3.0+) trabajan en números tan grandes es lo que estoy buscando.

Código que ilustra los tamaños:

>>> a=1 >>> print(a.__sizeof__()) 28 >>> a=1024 >>> print(a.__sizeof__()) 28 >>> a=1024*1024*1024 >>> print(a.__sizeof__()) 32 >>> a=1024*1024*1024*1024 >>> print(a.__sizeof__()) 32 >>> a=1024*1024*1024*1024*1024*1024 >>> a 1152921504606846976 >>> print(a.__sizeof__()) 36


¿Por qué 28 bytes inicialmente para cualquier valor tan bajo como 1 ?

Creo que @bgusach respondió eso completamente; Python usa estructuras C para representar objetos en el mundo de Python, cualquier objeto incluyendo int s :

struct _longobject { PyObject_VAR_HEAD digit ob_digit[1]; };

PyObject_VAR_HEAD es una macro que cuando se expande agrega otro campo en la estructura (campo PyVarObject que se usa específicamente para objetos que tienen alguna noción de longitud) y, ob_digits es una matriz que contiene el valor para el número. El tamaño de la placa de caldera proviene de esa estructura, para números pequeños y grandes de Python.

¿Por qué incrementos de 4 bytes?

Porque, cuando se crea un número mayor, el tamaño (en bytes) es un múltiplo del tamaño de sizeof(digit) ; Puedes ver eso en _PyLong_New donde la asignación de memoria para un nuevo objeto longobject se realiza con PyObject_MALLOC :

/* Number of bytes needed is: offsetof(PyLongObject, ob_digit) + sizeof(digit)*size. Previous incarnations of this code used sizeof(PyVarObject) instead of the offsetof, but this risks being incorrect in the presence of padding between the PyVarObject header and the digits. */ if (size > (Py_ssize_t)MAX_LONG_DIGITS) { PyErr_SetString(PyExc_OverflowError, "too many digits in integer"); return NULL; } result = PyObject_MALLOC(offsetof(PyLongObject, ob_digit) + size*sizeof(digit));

offsetof(PyLongObject, ob_digit) es la ''placa de la caldera'' (en bytes) para el objeto largo que no está relacionado con la retención de su valor.

digit se define en el archivo de encabezado que contiene struct _longobject como typedef para uint32 :

typedef uint32_t digit;

y sizeof(uint32_t) tiene 4 bytes. Esa es la cantidad por la que verá que el tamaño en bytes aumenta cuando aumenta el argumento de size a _PyLong_New .

Por supuesto, así es como C Python ha elegido implementarlo. Es un detalle de implementación y, como tal, no encontrará mucha información en PEP. La lista de correo de python-dev mantendría discusiones de implementación si puede encontrar el hilo correspondiente :-).

De cualquier manera, es posible que encuentre un comportamiento diferente en otras implementaciones populares, por lo que no lo tome por hecho.


En realidad es fácil. Python''s int no es el tipo de primitivo al que puedes estar acostumbrado en otros idiomas, sino un objeto completo, con sus métodos y todo lo demás. De ahí viene la sobrecarga.

Entonces, usted tiene la carga útil en sí misma, el número entero que se está representando. Y no hay límite para eso, excepto tu memoria.

El tamaño del int de Python es lo que necesita para representar el número más un poco de sobrecarga.

Si desea leer más a fondo, eche un vistazo a la parte relevante de la documentación :

Los enteros tienen una precisión ilimitada