Tout dans Python est un objet. Ainsi, la taille d'un int dans Python sera plus grande que d'habitude.
>>> sys.getsizeof(int())
24
OK, mais pourquoi faut-il 12 octets de plus pour 2⁶³
Par rapport à 2⁶³ - 1
Et pas un seul?
>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24
Je comprends que 2⁶³
Est long et 2⁶³-1
Un int, mais pourquoi 12 octets de différence?
Plus intuitif, j'ai essayé d'autres choses:
>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36
a
est toujours stocké en tant que long même s'il pourrait être dans un int maintenant. Donc ce n'est pas surprenant. Mais:
>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28
Une nouvelle taille.
>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24
Retour à 24 octets, mais toujours avec un long.
Dernière chose que j'ai eu:
>>> sys.getsizeof(long())
24
Question:
Comment fonctionne la mémoire de stockage dans ces scénarios?
Sous-questions:
Pourquoi y a-t-il un espace de 12 octets pour ajouter ce que notre intuition nous dit n'est qu'un bit?
Pourquoi int()
et long()
24 octets, alors que long(1)
a déjà 28 octets et int(2⁶²)
?
NB: Python 3.X fonctionne un peu différemment, mais pas de manière plus intuitive. Ici, je me suis concentré sur Python 2.7 ; Je n'ai pas testé sur les versions précédentes.
Bien que je ne l'ai pas trouvé dans la documentation, voici mon explication.
Python 2 promeut implicitement int
en long
, lorsque la valeur dépasse la valeur pouvant être stockée dans int. La taille du nouveau type (long
) est la taille par défaut de long
, qui est 32. Désormais, la taille de votre variable sera déterminée par sa valeur, qui peut aller haut et bas.
from sys import getsizeof as size
a = 1
n = 32
# going up
for i in range(10):
if not i:
print 'a = %100s%13s%4s' % (str(a), type(a), size(a))
else:
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a <<= n
# going down
for i in range(11):
print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
a >>= n
a = 1 <type 'int'> 24
a = 4294967296 <type 'long'> 32
a = 18446744073709551616 <type 'long'> 36
a = 79228162514264337593543950336 <type 'long'> 40
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576 <type 'long'> 68
a = 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a = 115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a = 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a = 6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a = 1461501637330902918203684832716283019655932542976 <type 'long'> 48
a = 340282366920938463463374607431768211456 <type 'long'> 44
a = 79228162514264337593543950336 <type 'long'> 40
a = 18446744073709551616 <type 'long'> 36
a = 4294967296 <type 'long'> 32
a = 1 <type 'long'> 28
Comme vous pouvez le constater, le type reste long
après qu’il soit devenu trop gros pour un int
, et la taille initiale était de 32, mais la taille change avec la valeur (peut être supérieure ou inférieure [ ou égal, évidemment] à 32)
Donc, pour répondre à votre question, la taille de base est 24 pour int
, et 28 pour long
, alors que long
dispose également de l'espace nécessaire pour enregistrer des valeurs élevées (qui commence par 4). octets - donc 32 octets pour long
, mais peut monter et descendre en fonction de la valeur)
Quant à votre sous-question, créer un type unique (avec une taille unique) pour un nouveau numéro est impossible, donc Python a des "sous-classes" de long
type, qui traiter avec une plage de nombres, donc, une fois que vous avez dépassé la limite de votre ancien long
, vous devez utiliser le plus récent, ce qui représente également des nombres beaucoup plus grands. Il a donc quelques octets de plus.