31 votes

Pourquoi une valeur False (0) est-elle plus petite en octets que True (1)?

J'ai été jouer avec syss' getsizeof() et a constaté que False (ou 0) se compose de moins d'octets que le nombre True (ou 1). Pourquoi est-ce?

import sys

print("Zero: " + str(sys.getsizeof(0)))
print("One: " + str(sys.getsizeof(1)))
print("False: " + str(sys.getsizeof(False)))
print("True: " + str(sys.getsizeof(True)))

# Prints:
# Zero: 24
# One: 28
# False: 24
# True: 28

En fait, d'autres numéros (aussi certains qui se composent de plus d'un chiffre) est de 28 octets.

for n in range(0, 12):
  print(str(n) + ": " + str(sys.getsizeof(n)))

# Prints:
# 0: 24
# 1: 28
# 2: 28
# 3: 28
# 4: 28
# 5: 28
# 6: 28
# 7: 28
# 8: 28
# 9: 28
# 10: 28
# 11: 28

Même plus: sys.getsizeof(999999999) est également de 28 octets! sys.getsizeof(9999999999), cependant, est de 32.

Alors que ce passe? Je suppose que les opérations booléennes True et False sont convertis en interne en 0 et 1 respectivement, mais pourquoi est zéro différents en taille à partir d'autres bas des entiers?

Côté question: est-ce spécifique à la façon Python (3) représente ces éléments, ou est-ce la façon dont les chiffres sont présentés dans l'OS?

32voto

abarnert Points 94246

Rappelez-vous que Python int des valeurs sont de taille arbitraire. Comment cela fonctionne?

Eh bien, en Disponible,1 un entier est représenté par un PyLong_Object, ce qui est un tableau de 4 octets morceaux de2, chacun détenant 30 bits3 vaut la peine de le nombre.

  • 0 prend pas de morceaux à tous.
  • 1 - (1<<30)-1 1 bloc.
  • 1<<30 - (1<<60)-1 2 morceaux.

Et ainsi de suite.

C'est un peu simpliste; pour plus de détails, reportez - longintrepr.h dans la source.


En Python 2, il existe deux types distincts, appelés int et long. Un int est représenté par un C entier signé 32 bits4 incorporé directement dans l'en-tête, au lieu d'un éventail de morceaux. Un long , c'est comme un Python de 3 int.

Si vous faites le même test avec des 0L, 1L, etc., demander explicitement long valeurs, vous obtiendrez les mêmes résultats qu'en Python 3. Mais sans l' L suffixe, littérale qui s'adapte en 32 bits vous donne un int, et uniquement des littéraux qui sont trop grands vous donner des longs.5 (Ce qui signifie qu' (1<<31)-1 est int, mais 1<<31 2-chunk long.)


1. Dans une autre mise en œuvre, cela pourrait ne pas être vrai. IIRC, Jython n'a à peu près la même chose que Disponible, mais IronPython en C# "bignum" la mise en œuvre.

2. Pourquoi 30 bits au lieu de 32? Principalement parce que la mise en œuvre de l' pow et ** peut être plus simple et plus rapide si l'on peut supposer que le nombre de bits dans les deux chiffres est divisible par 10.

3. Il utilise le C "struct hack". Techniquement, Py_LongObject 28 octets, mais personne n'a jamais alloue un Py_LongObject; ils malloc 24, 28, 32, 36, etc. octets puis jeté à l' Py_LongObject *.

4. En fait, un Python int C long,, juste pour rendre les choses encore plus confuses. Donc, l'API C est plein de choses comme PyInt_FromLong où l' long signifie "32 bits int" et PyLong_FromSize_t où l' long signifie "bignum".

5. Les premières versions de Python 2.x ne pas intégrer int et long en tant que bien, mais j'espère que personne n'a pas à s'inquiéter de plus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X