2011-11-18 10 views
8

Estoy acostumbrado a ver if obj is None: en Python, y recientemente encontré if obj is():. Dado que las tuplas no son mutables, parece una optimización interna razonable en el intérprete de Python que la tupla vacía sea un singleton, lo que permite el uso de is en lugar de requerir ==. Pero, ¿esto está garantizado en alguna parte? ¿Desde qué versión del intérprete?comparar el objeto para vaciar la tupla con el operador 'es' en Python 2.x

[editar] la pregunta es importante porque if() no es un singleton y hay una manera de producir una tupla vacía con una dirección diferente, entonces usar is {} es un error. Si solo está garantizado desde Python 2.x con x> 0, entonces es importante saber el valor de x si necesita asegurar la compatibilidad con versiones anteriores de su código. También es importante saber si esto puede romper su código cuando se utiliza PyPy/jython/IronPython ...

+0

Es, definitivamente, no idiomática. ¿Hay un caso de uso justificable para esto? –

+0

@StevenRumbalski: no hay caso de uso especial. Encontré código usando esto y me pregunté si debería cambiarlo o actualizar mi opinión sobre el operador "es".Tendría sentido implementar() como singleton en el nivel de intérprete ... –

Respuesta

11

Desde el Python 2 docs y Python 3 docs:

... dos apariciones de la tupla vacía puede o no producir el mismo objeto.

En otras palabras, no puede contar con () is() para evaluar como verdadero.

0

Vamos a usar el método id() obtener el ID interno del():

>>> id(()) 
140180995895376 
>>> empty_tuple =() 
>>> id(empty_tuple) 
140180995895376  # same as the id of() 
>>> from copy import copy 
>>> id(copy(empty_tuple)) 
140180995895376  # still the same as the id of() 

Parece al igual que el() se almacena efectivamente como singleton en python (al menos en python> 2.6).

Existe el mismo comportamiento para la variable de cadena vacía "".

+0

Solo por curiosidad, ¿qué pasa con '[]'? – Toomai

+0

este ejemplo no prueba nada: no muestra que 2 tuplas vacías creadas en 2 módulos diferentes serán el mismo objeto al final. Las cadenas literales están internados en Python (es el caso desde el principio de la rama 2.x), y aunque la cadena vacía también podría ser un singleton, no hay pruebas de que lo que ves no sea un efecto secundario de la práctica. –

+0

@Toomai: las listas son mutables, por lo que no puede tener la lista vacía como singleton. –

0

Este es un detalle de implementación no garantizado de las versiones actuales de CPython, por lo que no necesariamente podrá confiar en otras implementaciones de Python, incluidas Jython, IronPython, PyPy y versiones futuras potenciales de CPython.

Usando is parece ser de unos 0,04 μ s más rápido en mi sistema cuando se compara contra una gran lista:

$ python -m timeit -s "x = range(10000)" "x is()" 
10000000 loops, best of 3: 0.0401 usec per loop 

$ python -m timeit -s "x = range(10000)" "x ==()" 
10000000 loops, best of 3: 0.0844 usec per loop 

Por supuesto que podría ser considerablemente peor si usted está comparando contra algo con una costumbre __eq__() método:

$ python -m timeit -s $'import time\nclass X(object):\n def __eq__(self, other): return time.sleep(1)\nx = X()' "x ==()" 
10 loops, best of 3: 1e+03 msec per loop 

embargo, si esta diferencia de rendimiento es crítico, creo que sería apuntar a un problema de diseño.

0

No se trata de optimización. Se trata de comparaciones de objetos. Python "is" se usa para probar la identidad del objeto, luego compare la tupla vacía "()" no es necesaria para usar el operador "==". De hecho, cualquier cosa en Python se puede comparar con "es".

>>> obj =() 
>>> obj is() 
True 
>>> isinstance(obj, tuple) 
True 
>>> obj is tuple 
False 
>>> type(obj) is tuple 
True 
>>> type(()) 
<type 'tuple'> 
>>> type(tuple) 
<type 'type'> 
>>> tuple == type(()) # value comparison with == 
True 

Lo mismo para cualquier otro valor:

>>> 333 is int 
False 
>>> type(333) is int 
True 
>>> isinstance(333, int) 
True 
+1

Pero compare con la ejecución de las sentencias 'a = 257' y' b = 257'. 'a es b' puede devolver' False'. –

+0

Sí. Pero esto está relacionado con las partes internas de Python porque id (a) puede ser diferente de id (b). tipo (a) es tipo (b) siempre devuelve verdadero. Traté de mostrar que el operador "es" es más adecuado para las comparaciones de tipos, aunque también se pueden comparar objetos de instancias. –

+0

Excelente punto: la identidad debería funcionar al comparar tipos. Pero en ese caso, 'isinstance()' suele ser lo correcto para usar. –

Cuestiones relacionadas