Comment Python gère-t-il int et long?

118

Est-ce que quelqu'un sait comment Python gère en interne les types int et long?

  • Choisit-il le bon type de manière dynamique?
  • Quelle est la limite pour un int?
  • J'utilise Python 2.6, est-ce différent des versions précédentes?

Comment dois-je comprendre le code ci-dessous?

>>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>

Mettre à jour:

>>> print type(0x7fffffff)
<type 'int'>
>>> print type(0x80000000)
<type 'long'>
luc
la source
Ne sont-ils pas simplement mappés aux types stdc à la volée sous CPython?
Aiden Bell
Ouais, je pense qu'ils le font. Je soupçonne également que tout est alloué sur le tas, donc quand un nombre a besoin de plus de précision, realloctout va bien. Mais je ne suis pas tout à fait sûr, alors je vais laisser la réponse à quelqu'un d'autre.
zneak
2
Vous pouvez également forcer python à utiliser une variable longue avecvar = 666L
qba
8
@Ignacio: WRONG Un CPython intest un C long(la valeur par défaut est signée) ... voir <CPython 2.X source>/Include/intobject.h: typedef struct {PyObject_HEAD long ob_ival; } PyIntObject; Dans tous les cas, Python 2.x intautorise les nombres négatifs; un C unsignedne ferait tout simplement pas l'affaire.
John Machin
PEP 237 explique comment sous le capot, Python est censé rendre tout cela parfaitement identique.
Carel

Réponses:

124

intet longont été "unifiées" quelques versions en arrière . Avant cela, il était possible de déborder un int à travers des opérations mathématiques.

3.x a encore avancé cela en éliminant complètement long et en n'ayant que int.

  • Python 2 : sys.maxintcontient la valeur maximale qu'un int Python peut contenir.
    • Sur un Python 2.7 64 bits, la taille est de 24 octets. Vérifiez avec sys.getsizeof().
  • Python 3 : sys.maxsizecontient la taille maximale en octets qu'un int Python peut avoir.
    • Ce sera des gigaoctets en 32 bits et des exaoctets en 64 bits.
    • Un int aussi grand aurait une valeur similaire à 8 à la puissance de sys.maxsize.
Ignacio Vazquez-Abrams
la source
30
Mais Python3 appelle ce type «int», même s'il se comporte plus comme «long» de 2.x.
3
Commentaire de Ted: Comme mentionné ci-dessous, méfiez-vous que la conversion de quelque chose en int qui est plus grand que maxint entraînera toujours un type long >>> (int (sys.maxint + 1)) <type 'long'>
StuartLC
2
sys.maxint vous donnera le plus grand entier 64 bits (sur ma machine 64 bits) un Long peut être beaucoup plus grand que 64 bits, essayez simplement "sys.maxint << 1000000"
fccoelho
4
En python3, c'est sys.maxsize
pylover
3
sys.maxsize n'a rien à voir avec les entiers. Sys.maxint de Python 3 a été supprimé car il n'y a pas de taille maximale pour un entier (Python 3 intest le même que Python 2 long).
asmeurer
19

Ce PEP devrait aider.

En fin de compte, vous ne devriez vraiment pas avoir à vous en soucier dans les versions python> 2.4

mluebke
la source
15
Vous devez vous en préoccuper si vous devez appeler une fonction int dans c avec quelque chose qui ne rentre pas dans int (c'est-à-dire un long). Aucune quantité de casting long-> int n'aidera. Cela m'est arrivé récemment.
Macke
1
@Macke: Ce commentaire m'a sauvé, j'ai supposé que int ferait l'affaire, et je me demandais pourquoi j'obtenais toujours une exception Jython.
ted
@Macke Absolument vrai. Dans l'entreprise où je travaille actuellement, nous avons un simulateur écrit en Python qui prend les entrées de l'utilisateur via les entrées Tkinter et envoie les valeurs transtypées via TCP / IP à un client (écrit en C / C ++) qui imite un système embarqué. Imaginez ce qui se passe lorsque vous insérez 100000000000000000000000 dans votre entrée basée sur Python ...: P
rbaleksandar
@Mackie eh bien, si vous avez pris la peine de lire le PEP, il dit explicitement: L'API C reste inchangée; Le code C devra toujours être conscient de la différence entre les entiers courts et longs. (L'API C Python 3.0 sera probablement complètement incompatible.) Les API PyArg_Parse * () acceptent déjà des entiers longs, tant qu'ils sont dans la plage représentable par C entiers ou longs, de sorte que les fonctions prenant C int ou long argument l'emportent ' Vous n'avez pas à vous soucier des longs Python.
cowbert
4

Sur ma machine:

>>> print type(1<<30)
<type 'int'>
>>> print type(1<<31)
<type 'long'>
>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'long'>

Python utilise des entiers (entiers signés 32 bits, je ne sais pas si ce sont des entiers C sous le capot ou non) pour les valeurs qui tiennent dans 32 bits, mais passe automatiquement en longs (nombre arbitrairement grand de bits - c'est-à-dire bignums) pour quoi que ce soit plus grand. Je suppose que cela accélère les choses pour les valeurs plus petites tout en évitant les débordements avec une transition transparente vers les bignums.

MAK
la source
4

Intéressant. Sur ma boîte 64 bits (i7 Ubuntu):

>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'int'>

Je suppose que cela augmente jusqu'à 64 bits sur une machine plus grande.

Gringo Suave
la source
2
Python utilise le type entier le plus grand disponible pour la machine. Donc, généralement sur les machines 32 bits, int aura une taille de 32 bits, tandis que sur les machines 64 bits, il aura une taille de 64 bits. Mais il pourrait y avoir des architectures 32 bits définissant des entiers 64 bits, dans ce cas, python utiliserait l'entier 64 bits.
Bakuriu
4

Python 2.7.9 favorise automatiquement les nombres. Pour un cas où l'on n'est pas sûr d'utiliser int () ou long ().

>>> a = int("123")
>>> type(a)
<type 'int'>
>>> a = int("111111111111111111111111111111111111111111111111111")
>>> type(a)
<type 'long'>
nvd
la source
4

Python 2 définira automatiquement le type en fonction de la taille de la valeur. Vous trouverez ci-dessous un guide des valeurs maximales.

La valeur Max de l'Int par défaut dans Python 2 est 65535, tout ce qui est au-dessus sera long

Par exemple:

>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>

Dans Python 3, le type de données long a été supprimé et toutes les valeurs entières sont gérées par la classe Int. La taille par défaut de Int dépendra de l'architecture de votre CPU.

Par exemple:

  • Systèmes 32 bits, le type de données par défaut pour les entiers sera «Int32»
  • Systèmes 64 bits, le type de données par défaut pour les entiers sera «Int64»

Les valeurs min / max de chaque type se trouvent ci-dessous:

  • Int8: [-128.127]
  • Int16: [-32768,32767]
  • Int32: [-2147483648,2147483647]
  • Int64: [-9223372036854775808,9223372036854775807]
  • Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
  • UInt8: [0,255]
  • UInt16: [0,65535]
  • UInt32: [0,4294967295]
  • UInt64: [0,18446744073709551615]
  • UInt128: [0,340282366920938463463374607431768211455]

Si la taille de votre Int dépasse les limites mentionnées ci-dessus, python changera automatiquement son type et allouera plus de mémoire pour gérer cette augmentation des valeurs min / max. Là où dans Python 2, il se convertirait en `` long '', il se convertit maintenant simplement en la taille suivante de Int.

Exemple: Si vous utilisez un système d'exploitation 32 bits, la valeur maximale d'un Int sera 2147483647 par défaut. Si une valeur de 2147483648 ou plus est affectée, le type sera changé en Int64.

Il existe différentes façons de vérifier la taille de l'int et son allocation de mémoire. Remarque: dans Python 3, l'utilisation de la méthode intégrée type () retournera toujours <class 'int'>quelle que soit la taille Int que vous utilisez.

James Lane
la source
1

Depuis python 3.x, les libries d'entiers unifiés sont encore plus intelligentes que les anciennes versions. Sur ma boîte (i7 Ubuntu), j'ai obtenu ce qui suit,

>>> type(math.factorial(30))
<class 'int'>

Pour plus de détails sur la mise en œuvre, reportez-vous aux Include/longintrepr.h, Objects/longobject.c and Modules/mathmodule.cfichiers. Le dernier fichier est un module dynamique (compilé dans un fichier so). Le code est bien commenté à suivre.

Venki
la source
1

Juste pour continuer avec toutes les réponses qui ont été données ici, en particulier @James Lanes

la taille du type entier peut être exprimée par cette formule:

plage totale = (système 2 ^ bits)

limite inférieure = - (système 2 ^ bits) * 0,5 limite supérieure = ((système 2 ^ bits) * 0,5) - 1

Nader Belal
la source
0

Il les gère parce que intetlong sont des définitions de classe frères. Ils ont des méthodes appropriées pour +, -, *, /, etc., qui produiront des résultats de la classe appropriée.

Par exemple

>>> a=1<<30
>>> type(a)
<type 'int'>
>>> b=a*2
>>> type(b)
<type 'long'>

Dans ce cas, la classe inta une __mul__méthode (celle qui implémente *) qui crée un longrésultat si nécessaire.

S.Lott
la source