example python

sys python example



"Sys.getsizeof(int)" devuelve un valor irrazonablemente grande? (1)

La respuesta corta

Está obteniendo el tamaño de la clase , no de una instancia de la clase. Llame a int para obtener el tamaño de una instancia:

>>> sys.getsizeof(int()) 24

Si ese tamaño todavía parece un poco grande, recuerde que un int Python es muy diferente de un int en (por ejemplo) c. En Python, un int es un objeto de pleno derecho. Esto significa que hay sobrecarga adicional.

Cada objeto de Python contiene al menos un refcount y una referencia al tipo del objeto además de otro almacenamiento; En una máquina de 64 bits, que ocupa 16 bytes! Los internos internos (según lo determinado por la implementación estándar de CPython) también han cambiado con el tiempo, por lo que la cantidad de almacenamiento adicional que depende de su versión.

Algunos detalles sobre objetos int en Python 2 y 3

Aquí está la situación en Python 2. (Parte de esto está adaptado de una publicación de blog de Laurent Luce ). Los objetos enteros se representan como bloques de memoria con la siguiente estructura:

typedef struct { PyObject_HEAD long ob_ival; } PyIntObject;

PyObject_HEAD es una macro que define el almacenamiento para el refcount y el tipo de objeto. Se describe con cierto detalle en la documentation , y el código se puede ver en this respuesta.

La memoria se asigna en bloques grandes para que no haya un cuello de botella en la asignación para cada nuevo entero. La estructura del bloque se ve así:

struct _intblock { struct _intblock *next; PyIntObject objects[N_INTOBJECTS]; }; typedef struct _intblock PyIntBlock;

Estos están todos vacíos al principio. Luego, cada vez que se crea un nuevo número entero, Python utiliza la memoria apuntada por next y se incrementa al next del punto al siguiente objeto entero libre en el bloque.

No estoy completamente seguro de cómo esto cambia una vez que excede la capacidad de almacenamiento de un entero normal, pero una vez que lo hace, el tamaño de un int hace más grande. En mi máquina, en Python 2:

>>> sys.getsizeof(0) 24 >>> sys.getsizeof(1) 24 >>> sys.getsizeof(2 ** 62) 24 >>> sys.getsizeof(2 ** 63) 36

En Python 3, creo que la imagen general es la misma, pero el tamaño de los enteros aumenta de una manera más gradual:

>>> sys.getsizeof(0) 24 >>> sys.getsizeof(1) 28 >>> sys.getsizeof(2 ** 30 - 1) 28 >>> sys.getsizeof(2 ** 30) 32 >>> sys.getsizeof(2 ** 60 - 1) 32 >>> sys.getsizeof(2 ** 60) 36

¡Estos resultados son, por supuesto, dependientes del hardware! YMMV.

La variabilidad en el tamaño de enteros en Python 3 es un indicio de que pueden comportarse más como tipos de longitud variable (como listas). Y de hecho, esto resulta ser cierto. Aquí está la definición de la struct C para objetos int en Python 3:

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

Los comments que acompañan a esta definición resumen la representación de enteros de Python 3. El cero no está representado por un valor almacenado, sino por un objeto con un tamaño cero (por lo que sys.getsizeof(0) es de 24 bytes, mientras que sys.getsizeof(1) es 28 ). ¡Los números negativos están representados por objetos con un atributo de tamaño negativo! Tan raro.

Quiero verificar el tamaño del tipo de datos int en python:

import sys sys.getsizeof(int)

Resulta ser "436", lo que no tiene sentido para mí. De todos modos, quiero saber cuántos bytes (2,4, ..?) Int tomarán en mi máquina.