512 votos

Python "es" operador se comporta de forma inesperada con números enteros

¿Por qué el siguiente comportarse de forma inesperada en Python?

>>> a = 256
>>> b = 256
>>> a is b
True           # this is an expected result
>>> a = 257
>>> b = 257
>>> a is b
False          # what happened here? why is this False?
>>> 257 is 257
True           # yet the literal numbers compare properly

Estoy usando Python 2.5.2. Tratando de algunas de las diferentes versiones de Python, parece que una de Python 2.3.3 muestra el anterior comportamiento entre el 99 y 100.

Con base en lo anterior, me puede la hipótesis de que Python es implementada internamente dicho que "los pequeños" a los enteros se almacenan en una manera diferente a los grandes números enteros, y el is operador puede decir la diferencia. ¿Por qué la permeabilidad de la abstracción? Lo que es una mejor manera de comparar dos objetos arbitrarios para ver si son el mismo, y no sé de antemano si se trata de números o no?

395voto

Cybis Puntos 5062

Echa un vistazo a esto:

>>> a = 256
>>> b = 256
>>> id(a)
9987148
>>> id(b)
9987148
>>> a = 257
>>> b = 257
>>> id(a)
11662816
>>> id(b)
11662828

EDIT: Aquí está lo que he encontrado en la documentación de Python, 7.2.1, "Llano Entero Objetos":

La implementación actual mantiene una matriz de enteros objetos para todos enteros entre -5 y 256, cuando se crear un int en que rango de en realidad, acaba de obtener de nuevo una referencia a el objeto existente. Por lo que debe ser posible cambiar el valor de 1. Yo sospechoso el comportamiento de Python en este caso es indefinido. :-)

60voto

JimB Puntos 9246

Depende de si usted está mirando para ver si las 2 cosas son iguales, o el mismo objeto.

"es", se comprueba si son el mismo objeto, no sólo la igualdad. El pequeño enteros son probablemente apuntando a la misma ubicación de memoria para el espacio de la eficiencia

In [29]: a = 3
In [30]: b = 3
In [31]: id(a)
Out[31]: 500729144
In [32]: id(b)
Out[32]: 500729144

Usted debe utilizar "==" para comparar la igualdad de objetos arbitrarios. Usted puede especificar el comportamiento con el __eq__y __ne__ atributos.

37voto

Angel Puntos 616

Como se puede comprobar aquí de Python cachés pequeñas enteros para la eficiencia. Cada vez que se crea una referencia a un pequeño int, se está refiriendo a la caché pequeña int, no un objeto nuevo. 257 no es un pequeño int, por lo que se calcula como un objeto diferente.

Es mejor usar "==" para ese propósito.

19voto

Amit Puntos 503

Creo que su hipótesis es correcta. Experimento con id (identidad de objeto)..

In [1]: id(255)
Out[1]: 146349024

In [2]: id(255)
Out[2]: 146349024

In [3]: id(257)
Out[3]: 146802752

In [4]: id(257)
Out[4]: 148993740

In [5]: a=255

In [6]: b=255

In [7]: c=257

In [8]: d=257

In [9]: id(a), id(b), id(c), id(d)
Out[9]: (146349024, 146349024, 146783024, 146804020)

Parece que los números <= 255 son tratados como literales y nada de lo anterior es tratada de forma diferente!

16voto

thereisnospork Puntos 169

El 'es' operador no es otra forma de escribir '=='.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X