Python admite los siguientes operadores de comparación básicos:
| 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 a y b no son el mismo objeto
|
in |
«comprobación de pertenencia» |
a in b es True si a es miembro, subconjunto o elemento de b
|
not in |
«comprobación 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 Boolean, pero menor que la de las operaciones aritméticas o bit a bit).
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 no 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 de object.
La personalización mediante rich comparisons se tratará en un ejercicio posterior.
Para obtener (muchos) más detalles sobre este tema, 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 puedan convertirse implícitamente para la comparación.
Para los demás tipos numéricos de la biblioteca estándar de Python (complejos, decimales, fracciones), los operadores de comparación están definidos donde «tienen sentido» (donde la conversión implícita no cambia el resultado), pero lanzan un TypeError si los objetos subyacentes no pueden convertirse 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.
>>> x = float('NaN')
>>> 3 < x
False
>>> x < 3
False
# NaN never compares equal to NaN
>>> x == x
False
A diferencia de los números, 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 de forma «por pares»: el primero con el primero, el segundo con el segundo, etc.
En Python 3.x, str y bytes no pueden convertirse ni compararse 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 operadores de comparación pueden encadenarse de forma arbitraria, lo que significa que pueden usarse en cualquier combinación y con cualquier longitud.
Ten en cuenta que la evaluación de una expresión se realiza de left a right.
Por ejemplo, x < y <= z es equivalente 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 x < y resulta ser False.
A esto se le suele llamar short-circuit evaluation: la evaluación se detiene si el valor de verdad de la expresión ya se ha determinado.
Short circuiting es compatible con varios operadores Boolean, funciones 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 a su valor.
La identidad de un objeto nunca cambia después de su creación y puede obtenerse 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> devuelve lo contrario.
Debido a su condición de singleton, None y NotImplemented siempre deben compararse con 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.
>>> 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 él), 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
En este ejercicio vas a implementar algunas reglas del blackjack, como la forma en que se juega y se puntúa.
Nota: en este ejercicio, A significa as, J significa jota, Q significa reina y K significa rey.
Los comodines se descartan.
Se asume una baraja estándar francesa de 52 cartas, aunque en la mayoría de las versiones se barajan juntas varias barajas para jugar.
En el blackjack, cada jugador decide si un as vale 1 u 11 puntos (sobre esto hablaremos más adelante).
Las figuras (J, Q, K) puntúan 10 puntos y cualquier otra carta vale su «pip» (el valor numérico).
Define la función value_of_card(<card>) con el parámetro card.
La función debe devolver el valor numérico del string de la carta que se le pasa.
Como un as puede tomar varios valores (1 o 11), esta función debe fijar por ahora el valor de un as en 1.
Más adelante implementarás una función para determinar el valor de un as dada una mano existente.
>>> value_of_card('K')
10
>>> value_of_card('4')
4
>>> value_of_card('A')
1
Define la función higher_card(<card_one>, <card_two>) con los parámetros card_one y card_two.
A efectos de puntuación, el valor de J, Q o K es 10.
La función debe devolver cuál de las cartas tiene el valor más alto a efectos de puntuación.
Si ambas cartas tienen el mismo valor, devuelve las dos.
Puedes devolver las dos cartas usando una coma en la instrucción return:
# Using a comma in a return creates a Tuple. Tuples will be covered in a later exercise.
>>> def returning_two_values(value_one, value_two):
return value_one, value_two
>>> returning_two_values('K', '3')
('K', '3')
Un as puede tomar varios valores, así que para esta tarea fijaremos las cartas A en un valor de 1.
>>> higher_card('K', '10')
('K', '10')
>>> higher_card('4', '6')
'6'
>>> higher_card('K', 'A')
'K'
Como ya hemos mencionado, un as puede valer 1 o 11 puntos. Los jugadores intentan acercarse lo más posible a una puntuación de 21, sin pasarse de 21 (lo que se conoce como «bust»).
Define la función value_of_ace(<card_one>, <card_two>) con los parámetros card_one y card_two, que son un par de cartas que ya están en la mano antes de recibir un as.
Tu función tendrá que decidir si el próximo as recibirá un valor de 1 o de 11, y devolver ese valor.
Recuerda: el valor de la mano con el as debe ser lo más alto posible, sin pasarse de 21.
Pista: si ya tenemos un as en la mano, el valor del próximo as sería 1.
>>> value_of_ace('6', 'K')
1
>>> value_of_ace('7', '3')
11
Si a un jugador le reparten un as (A) y una carta de diez (10, K, Q o J) como sus dos primeras cartas, el jugador tiene una puntuación de 21.
Esto se conoce como una mano de blackjack.
Define la función is_blackjack(<card_one>, <card_two>) con los parámetros card_one y card_two, que son un par de cartas.
Determina si la mano de dos cartas es un blackjack y devuelve el valor booleano True si lo es, o False en caso contrario.
Nota: el cálculo de la puntuación se puede hacer de muchas maneras. Pero, si es posible, nos gustaría que comprobaras si hay un as y una carta de diez en la mano (o en una posición determinada), en lugar de sumar los valores de la mano.
>>> is_blackjack('A', 'K')
True
>>> is_blackjack('10', '9')
False
Si las dos primeras cartas de una mano tienen el mismo valor (por ejemplo, dos seises o una Q y una K), el jugador puede optar por tratarlas como dos manos separadas.
Esto se conoce como «dividir parejas».
Define la función can_split_pairs(<card_one>, <card_two>) con los parámetros card_one y card_two, que son un par de cartas.
Determina si esta mano de dos cartas se puede dividir en dos parejas.
Si la mano se puede dividir, devuelve el valor booleano True; en caso contrario, devuelve False.
>>> can_split_pairs('Q', 'K')
True
>>> can_split_pairs('10', 'A')
False
Cuando las dos cartas originales repartidas suman 9, 10 u 11 puntos, el jugador puede hacer una apuesta adicional igual a su apuesta original. Esto se conoce como «doblar la apuesta».
Define la función can_double_down(<card_one>, <card_two>) con los parámetros card_one y card_two, que son un par de cartas.
Determina si la mano de dos cartas se puede «doblar» y devuelve el valor booleano True si puede, o False en caso contrario.
>>> can_double_down('A', '9')
True
>>> can_double_down('10', '2')
False
Regístrate en Exercism para aprender y dominar Python con 17 conceptos146 ejercicios y mentoría humana real, todo gratis.