¿Cuándo usar == y cuándo usar?

Curiosamente:

>>> a = 123 >>> b = 123 >>> a is b True >>> a = 123. >>> b = 123. >>> a is b False 

Parece que a is b siendo más o menos definido como id(a) == id(b) . Es fácil hacer errores de esta manera:

 basename, ext = os.path.splitext(fname) if ext is '.mp3': # do something else: # do something else 

Algunos nombres terminaron inesperadamente en el bloque else. La solución es simple, deberíamos usar ext == '.mp3' lugar, pero no obstante, if ext is '.mp3' en la superficie parece una buena forma pythonica de escribir esto y es más legible que la forma “correcta”.

Dado que las cuerdas son inmutables, ¿cuáles son los detalles técnicos de por qué está mal? ¿Cuándo es mejor un control de identidad y cuándo es mejor un control de igualdad?

Por lo que puedo decir, is verificación de la equivalencia de la identidad del objeto. Como no hay “internado de cadena” obligatorio, las dos cadenas que simplemente tienen los mismos caracteres en secuencia no son, por lo general, el mismo objeto de cadena.

Cuando extraes una subcadena de una cadena (o, en realidad, cualquier subsecuencia de una secuencia), terminarás con dos objetos diferentes, que contienen el mismo valor (es).

Por lo tanto, el uso is cuando y solo cuando se comparan identidades de objetos. Use == cuando compare valores.

Son fundamentalmente diferentes.

  1. == compara llamando al método __eq__
  2. devuelve true si y solo si las dos referencias son al mismo objeto

Así que en comparación con decir Java:

  1. is lo mismo que == para objetos
  2. == es lo mismo que equals para los objetos

Regla simple para determinar si usar es o == en Python

Aquí hay una regla fácil (a menos que quiera ir a la teoría en el intérprete de Python o crear marcos de trabajo haciendo cosas divertidas con objetos de Python):

El uso es solo para ninguna comparación.

 if foo is None 

De lo contrario, utilice ==.

 if x == 3 

Entonces estás en el lado seguro. La justificación de esto ya está explicada en los comentarios anteriores. No lo uses si no estás 100% seguro de por qué hacerlo.

También sería útil definir una clase como esta para usarla como el valor predeterminado para las constantes utilizadas en su API. En este caso, sería más correcto usarlo que el operador ==.

 class Sentinel(object): """A constant object that does not change even when copied.""" def __deepcopy__(self, memo): # Always return the same object because this is essentially a constant. return self def __copy__(self): # called via copy.copy(x) return self