131 votes

Pourquoi (0-6) -6 = False?

Double Possible:
Python “est” l'opérateur se comporte de manière inattendue avec des entiers

Aujourd'hui, j'ai essayé de déboguer mon projet et après quelques heures de l'analyse que j'avais obtenu ceci:

>>> (0-6) is -6
False

mais,

>>> (0-5) is -5
True

Pourriez-vous m'expliquer, pourquoi? C'est peut-être une sorte de bug ou un comportement très étrange.

> Python 2.7.3 (default, Apr 24 2012, 00:00:54) [GCC 4.7.0 20120414 (prerelease)] on linux2
>>> type(0-6) 
<type 'int'>
>>> type(-6) 
<type 'int'>
>>> type((0-6) is -6)
<type 'bool'>
>>> 

155voto

KennyTM Points 232647

Tous les entiers à partir de -5 à 256 compris, sont mis en cache comme des objets globaux partage la même adresse Disponible, donc l' is test passe.

Cet artefact est expliqué en détail dans http://www.laurentluce.com/posts/python-integer-objects-implementation/, et on a pu vérifier le code source de courant en http://hg.python.org/cpython/file/tip/Objects/longobject.c.

Une structure spécifique est utilisé pour désigner les petits entiers et de les partager afin que l'accès est rapide. C'est un ensemble de 262 pointeurs vers des entiers objets. Ceux integer objets sont alloués au cours de l'initialisation dans un bloc entier d'objets nous avons vu ci-dessus. Le petit des entiers allant de -5 à 257. De nombreux programmes Python passer beaucoup de temps à l'aide de nombres entiers dans cette gamme c'est une décision intelligente.

Ce n'est qu'un détail d'implémentation de Disponible et vous ne devriez pas compter sur cette. Par exemple, PyPy mise en œuvre de l' id de l'entier de retourner lui-même, de sorte (0-6) is -6 est toujours vrai, même si ils sont "différents objets" à l'interne; il vous permet également de configurer si vous souhaitez activer cette entier de la mise en cache, et même définir les limites inférieure et supérieure. Mais, en général, des objets récupérés à partir d'origines différentes ne seront pas identiques. Si vous voulez comparer l'égalité, il suffit d'utiliser ==.

30voto

Simeon Visser Points 30697

Python magasins entiers dans la plage de -5 - 256 dans l'interpréteur: il dispose d'une piscine de entier des objets à partir de laquelle ces entiers sont retournés. C'est pourquoi ces objets sont les mêmes: (0-5) et -5 mais pas (0-6) et -6 que ceux-ci sont créés sur place.

Voici le code source dans le code source de Disponible:

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

(vue Disponible le code source: /trunk/Objects/intobject.c). Le code source comprend le commentaire suivant:

/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/

L' is opérateur de les comparer (-5) égal parce qu'ils sont le même objet (même emplacement de mémoire), mais les deux autres nouvelles entiers (-6) sera à différents emplacements de mémoire (et puis, is ne sera pas de retour True). Notez que 257 dans le ci-dessus le code source est pour les entiers positifs, donc c'est - 0 - 256 (inclus).

(source)

27voto

Russell Borogove Points 8423

Ce n'est pas un bug. is n'est pas un test d'égalité. == donnera les résultats escomptés.

La technique de la raison de ce comportement est qu'un Python de la mise en œuvre est libre de traiter les différentes instances de la même valeur constante comme le même objet, ou comme des objets différents. Le Python de mise en œuvre vous utilisez choisit de faire certaines petites constantes de partager le même objet en mémoire raisons d'économie. Vous ne pouvez pas compter sur ce comportement étant la même version à l'autre ou à travers les différentes implémentations de Python.

17voto

Ashwini Chaudhary Points 94431

Cela se passe parce que python caches de certains petits entiers et des petites chaînes et donne à chaque instance de ce nombre particulier d'un même id().

(0-5) et -5 a la même valeur pour l' id(), ce qui n'est pas vrai pour 0-6 et -6

>>> id((0-6))
12064324
>>> id((-6))
12064276
>>> id((0-5))
10022392
>>> id((-5))
10022392

De même pour les chaînes :

>>> x='abc'
>>> y='abc'
>>> x is y
True
>>> x='a little big string'
>>> y='a little big string'
>>> x is y
False

Pour plus de détails sur la corde de mise en cache, lire: is opérateur se comporte différemment lorsque l'on compare les chaînes de caractères avec des espaces

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