Un operador de comparación en Python (también llamado operador relacional de Python), examina los valores de dos operandos y devuelve True o False según si se cumple o no la condición de la comparación.
En la siguiente tabla se muestran los operadores de comparación de Python más comunes:
| Operador | Operación | Descripción |
|---|---|---|
> |
«mayor que» |
a > b es True si a es estrictamente mayor en valor que b
|
< |
«menor que» |
a < b es True si a es estrictamente menor en valor que b
|
== |
«igual a» |
a == b es True si a es estrictamente igual a b en valor |
>= |
«mayor o igual que» |
a >= b es True si a > b O a == b en valor |
<= |
«menor o igual que» |
a <= b es True si a < b o a == b en valor |
!= |
«distinto de» |
a != b es True si a == b es False
|
is |
«identidad» |
a is b es True si y solo si a y b son el mismo objeto
|
is not |
«identidad negada» |
a is not b es True si y solo si a y b no son el mismo objeto
|
in |
«prueba de pertenencia» |
a in b es True si a es miembro, subconjunto o elemento de b
|
not in |
«prueba de pertenencia negada» |
a not in b es True si a no es miembro, subconjunto o elemento de b
|
Todos tienen la misma prioridad (que es mayor que la de las operaciones booleanas, pero menor que la de las operaciones aritméticas o a nivel de bits).
Los objetos de tipos distintos (excepto los tipos numéricos) nunca se comparan como iguales de forma predeterminada.
Las instancias no idénticas de una class tampoco se compararán como iguales a menos que la class defina métodos especiales de comparación enriquecida que personalicen el comportamiento de comparación predeterminado del object.
Para (mucho) más detalle, consulta Comparaciones de valores en la documentación de Python.
Los tipos numéricos son (en su mayoría) una excepción a esta regla de coincidencia de tipos.
Un integer puede considerarse igual a un float (o un octal igual a un hexadecimal), siempre que los tipos se puedan convertir implícitamente para la comparación.
Para los demás tipos numéricos (números complejos, números decimales, números racionales), los operadores de comparación se definen donde «tienen sentido» (donde la conversión implícita no cambia el resultado), pero lanzan un TypeError si los objetos subyacentes no se pueden convertir con precisión para la comparación.
Para obtener más información sobre las reglas que usa Python para la conversión numérica, consulta conversiones aritméticas en la documentación de Python.
>>> import fractions
# A string cannot be converted to an int.
>>> 17 == '17'
False
# An int can be converted to float for comparison.
>>> 17 == 17.0
True
# The fraction 6/3 can be converted to the int 2
# The int 2 can be converted to 0b10 in binary.
>>> 6/3 == 0b10
True
# An int can be converted to a complex
# number with a 0 imaginary part.
>>> 17 == complex(17)
True
# The fraction 2/5 can be converted to the float 0.4
>>> 0.4 == 2/5
True
>>> complex(2/5, 1/2) == complex(0.4, 0.5)
True
Cualquier comparación ordenada de un número con un tipo NaN (no es un número) es False.
Un efecto secundario confuso de la definición de NaN en Python es que NaN nunca se compara como igual a NaN.
Si tienes curiosidad sobre por qué NaN se definió así en Python, esta publicación de Stack Overflow sobre NaN en torno al establecimiento del estándar internacional es una lectura interesante.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
Los strings (str) se comparan lexicográficamente, usando sus puntos de código Unicode individuales (el resultado de pasar cada punto de código del str a la función integrada ord(), que devuelve un int).
Si todos los puntos de código de ambos strings coinciden y están en el mismo orden, los dos strings se consideran iguales.
Esta comparación se hace por parejas: primero con primero, segundo con segundo, etc.
En Python 3.x, str y bytes no se pueden forzar ni comparar directamente.
>>> 'Python' > 'Rust'
False
>>> 'Python' > 'JavaScript'
True
# Examples with Mandarin.
# hello < goodbye
>>> '你好' < '再见'
True
# ord() of first characters
>>> ord('你'), ord('再')
(20320, 20877)
# ord() of second characters
>>> ord('好'), ord('见')
(22909, 35265)
# And with Korean words.
# Pretty < beautiful.
>>> '예쁜' < '아름다운'
False
>>> ord('예'), ord('아')
(50696, 50500)
Los tipos de datos contenedores (lists, tuples, sets, dicts, etc.) también se comparan lexicográficamente: son iguales si ambos contenedores tienen los mismos datos y los mismos tipos de datos (en el caso de lists y tuples, también deben tener el mismo orden), y desiguales en caso contrario.
>>> [1, 2] == [1, 2]
True
# But if the data is not in the same order, they are not equal.
>>> [2, 1] == [1, 2]
False
# The same holds true for tuples
>>> (3,4,5) == (5,4,3)
False
# Length is also compared
>>> [1, 2] < [1, 2, 3]
True
# Comparing dicts
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 18}
False
>>> {'name': 'John', 'age': 19} == {'name': 'John', 'age': 19}
True
Los operadores de comparación se pueden encadenar de forma arbitraria.
Ten en cuenta que la evaluación de una expresión se realiza de left a right.
Por ejemplo, x < y <= z equivale a x < y and y <= z, salvo que y se evalúa solo una vez.
En ambos casos, z no se evalúa en absoluto cuando se determina que x < y es False.
A esto se le suele llamar short-circuit evaluation: la evaluación se detiene si ya se ha determinado el valor de verdad de la expresión.
Short circuiting es compatible con varios operadores y funciones booleanos, y también con el encadenamiento de comparaciones en Python.
A diferencia de muchos otros lenguajes de programación, como C, C++, C# y Java, las expresiones encadenadas como a < b < c en Python tienen una interpretación matemática y una precedencia convencionales.
>>> x = 2
>>> y = 5
>>> z = 10
>>> x < y < z
True
>>> x < y > z
False
>>> x > y < z
False
Los operadores is y is not comprueban la identidad de un objeto, en contraposición al valor del objeto.
La identidad de un objeto nunca cambia después de su creación y se puede obtener con la función id().
<apple> is <orange> se evalúa como True si y solo si id(<apple>) == id(<orange>).
<apple> is not <orange> da el resultado inverso.
Debido a su condición de singleton, None y NotImplemented siempre deberían compararse con los elementos usando is y is not.
Consulta la documentación de referencia de Python sobre comparaciones de valores y PEP8 para obtener más detalles sobre esta convención.
# A list of favorite numbers.
>>> my_fav_numbers = [1, 2, 3]
>>> your_fav_numbers = my_fav_numbers
>>> my_fav_numbers is your_fav_numbers
True
# The returned id will differ by system and Python version.
>>> id(my_fav_numbers)
4517478208
# your_fav_numbers is only an alias pointing to the original my_fav_numbers object.
# Assigning a new name does not create a new object.
>>> id(your_fav_numbers)
4517478208
>>> my_fav_numbers is not your_fav_numbers
False
>>> my_fav_numbers is not None
True
>>> my_fav_numbers is NotImplemented
False
Los operadores in y not in comprueban la pertenencia.
<fish> in <soup> se evalúa como True si <fish> es miembro de <soup> (si <fish> es un subconjunto de <soup> o está contenido en comparison), y se evalúa como False en caso contrario.
<fish> not in <soup> devuelve la negación, o lo contrario de <fish> in <soup>.
Para los tipos string y bytes, <name> in <fullname> es True si y solo si <name> es una subcadena de <fullname>.
# A set of lucky numbers.
>>> lucky_numbers = {11, 22, 33}
>>> 22 in lucky_numbers
True
>>> 44 in lucky_numbers
False
# A dictionary of employee information.
>>> employee = {'name': 'John Doe', 'id': 67826, 'age': 33, 'title': 'ceo'}
# Checking for the membership of certain keys.
>>> 'age' in employee
True
>>> 33 in employee
False
>>> 'lastname' not in employee
True
# Checking for substring membership
>>> name = 'Super Batman'
>>> 'Bat' in name
True
>>> 'Batwoman' in name
False
El comportamiento de comparación de los objetos se puede personalizar mediante la implementación de rich comparison methods.
Para obtener más información, consulta Python Tutorial: classes, Python Classes and Magic Methods (Dan Bader) y Special method names.