Python: Resultados de expresiones lógicas
En esta lección aprenderemos las reglas de transformación de argumentos y cómo trabajar con expresiones compuestas y doble negación.
Reglas de transformación
El operador OR funciona de tal manera que se interrumpe la ejecución de izquierda a derecha y se devuelve el resultado del primer argumento que se pueda transformar en True
. Si no hay ningún argumento que cumpla esta condición, se devuelve el último argumento, el de la derecha.
Veamos un ejemplo:
print(0 or 1) ## 1
En este caso, el número 0
es equivalente a False
, y el número 1
es equivalente a True
. Por lo tanto, el operador OR devuelve 1
, ya que es el primer argumento que se puede transformar en True
.
Veamos un ejemplo más complejo:
print(0 or False or '' or [] or 42 or "Hello") ## 42
En este caso:
- El número
0
es equivalente aFalse
- El valor
False
ya esFalse
- La cadena vacía (
''
) es equivalente aFalse
- La lista vacía (
[]
) es equivalente aFalse
- El número
42
es equivalente aTrue
- La cadena
"Hello"
también es equivalente aTrue
El operador OR verifica los valores de izquierda a derecha y devuelve el primer argumento que se pueda transformar en True
. En este ejemplo, ese valor es el número 42
.
Ejemplo con el operador AND:
print(0 and 1) ## 0
El operador AND funciona de tal manera que se interrumpe la ejecución de izquierda a derecha y se devuelve el resultado del primer argumento que se pueda transformar en False
. Si no hay ningún argumento que cumpla esta condición, se devuelve el último argumento, el de la derecha.
print(42 and "Hello" and [] and 0) ## []
En este caso:
- El número
42
es equivalente aTrue
- La cadena
"Hello"
es equivalente aTrue
- La lista vacía (
[]
) es equivalente aFalse
- El número
0
es equivalente aFalse
El operador AND verifica los valores de izquierda a derecha y devuelve el primer argumento que se pueda transformar en False
. En este ejemplo, ese valor es la lista vacía ([]
).
En Python hay dos reglas de transformación:
0
,0.0
,''
yNone
se convierten enFalse
. Estos valores se llaman falsy. También hay otros tipos de datos que aprenderemos en Hexlet.- Todo lo demás se convierte en
True
Estas reglas se utilizan en el desarrollo, por ejemplo, para definir un valor por defecto:
value = name or ''
# Ejemplos
234 or '' # 234
'hexlet' or '' # 'hexlet'
None or '' # ''
Si nombre
tiene uno de los valores falsy, se asignará una cadena vacía a la variable valor
. En este caso, en el código posterior podremos trabajar con valor
como si fuera una cadena.
Pero aquí hay un posible error. Si nombre
contiene un valor falsy y se puede asignar a la variable valor
un valor como 0
, False
, None
, entonces el código anterior no funcionará correctamente:
# El valor realmente existe,
# pero es Falsy, por lo que no se selecciona en la condición OR
False or '' # ''
0 or '' # ''
None or '' # ''
Expresiones compuestas
Si se combinan expresiones lógicas entre sí, se pueden obtener formas interesantes de resolver problemas con código.
Supongamos que queremos implementar un código en el que una variable se asigna:
- La cadena
yes
si el número es par - La cadena
no
si el número es impar
Esto se puede hacer utilizando los conocimientos que hemos adquirido anteriormente:
# el número es par
resultado = 10 % 2 == 0 and 'yes' or 'no' # 'yes'
# o imprimir directamente en la pantalla
print(10 % 2 == 0 and 'yes' or 'no') # => 'yes'
# el número es impar
print(11 % 2 == 0 and 'yes' or 'no') # => 'no'
Estas expresiones funcionan según el orden y la prioridad. La asignación tiene la prioridad más baja, por lo que ocurre al final. La comparación ==
tiene una prioridad más alta que los operadores lógicos and
y or
, por lo que se realiza antes. Luego, el código se ejecuta de izquierda a derecha, ya que la prioridad de and
es mayor que la de or
. Veamos los pasos:
# Para un número par
# 1 paso
10 % 2 == 0 # True
# 2 paso
True and 'yes' # Resultado: verdadero
# La comprobación de or se realiza, pero la parte derecha no se ejecuta, ya que se devuelve inmediatamente 'yes'
# Para un número impar
# 1 paso
11 % 2 == 0 # False
# 2 paso
False and 'yes' # Resultado: falso, se sigue comprobando
# 3 paso
False or 'no' # Se selecciona y devuelve 'no'
Se puede utilizar el mismo esquema con cualquier expresión al principio:
print(somefunc() and 'yes' or 'no')
Puedes probar y experimentar con el código en https://replit.com/@hexlet/python-basics-logical-expressions).
Doble Negación
Recordemos cómo se ve una operación de negación:
answer = True
print(not answer) # => False
Con una doble negación, el valor final es igual al valor inicial:
answer = True
print(not not answer) # => True
El operador not
siempre devuelve un valor booleano, independientemente del tipo de argumento proporcionado, y no cambia el valor al opuesto. Por lo tanto, la doble negación también devolverá un Verdadero/Falso booleano.
answer = 'python'
print(not answer) # => False
print(not not answer) # => True
Error de Elección
Imagina que necesitamos comprobar si el valor es igual a uno u otro. Por ejemplo, la variable value
debe contener uno de dos valores: first
o second
. Los desarrolladores novatos a veces escriben esta expresión de esta manera:
value == ('first' or 'second')
Sin embargo, este código dará un resultado incorrecto. Debes recordar la prioridad de las operaciones. Primero, se evalúa todo lo que está dentro de los paréntesis: 'first' or 'second'
. Si ejecutas este código en Replit, la salida será la siguiente:
python
Python 3.8.2 (default, Apr 12 2020, 15:53:37)
>>> 'first' or 'second'
'first'
>>>
Ahora reemplacemos la expresión original con la expresión parcialmente evaluada:
value == 'first'
No es en absoluto lo que esperábamos. Y ahora volvamos al inicio y escribamos la verificación correctamente:
# No es necesario colocar paréntesis,
# porque la prioridad de == es mayor que la de or
value == 'first' or value == 'second'
Tarea
Implementa la función string_or_not()
que verifica si el parámetro proporcionado es una cadena correcta. Si lo es, devolverá como resultado 'yes'
, de lo contrario, devuelve 'no'
string_or_not('Hexlet') # 'yes'
string_or_not(10) # 'no'
string_or_not('') # 'yes'
string_or_not(False) # 'no'
Puedes verificar si el parámetro proporcionado es una cadena utilizando la función isinstance():
isinstance(3, str) # False
isinstance('Hexlet', str) # True
Experimenta con el código en la ventana interactiva REPL https://replit.com/@hexlet/python-basics-logical-expressions
¿El ejercicio no pasa la prueba, qué debo hacer? 😶
Si te quedaste atascado, es el momento perfecto para hacer una pregunta en las "Discusiones".
* Asegúrate de incluir la salida de las pruebas. Sin ella, es casi imposible entender qué está mal, incluso si muestras tu código. Los programadores tienen dificultades para ejecutar el código en su mente, pero casi siempre es posible entender a dónde mirar a partir del error que recibiste.
Mi código funciona en mi entorno, pero no aquí 🤨
Las pruebas están diseñadas de manera que verifican la solución de diferentes maneras y con diferentes datos. A menudo, una solución funciona con ciertos datos de entrada pero no con otros. Para entender este punto, revisa la pestaña "Pruebas" y presta atención a los mensajes de error, que suelen contener pistas.
Mi código es diferente a la solución del profesor 🤔
Esto es normal 🙆. En programación, una tarea puede tener muchas soluciones diferentes. Si tu código pasa la prueba, cumple con los requisitos de la tarea.
En raras ocasiones, la solución puede estar ajustada para pasar las pruebas, pero esto suele ser evidente.
Leí la lección, pero no entendí nada 🙄
Crear materiales de aprendizaje comprensibles para todos es bastante difícil. Hacemos nuestro mejor esfuerzo, pero siempre hay margen para mejorar. Si encuentras material que no entiendes, describe el problema en las "Discusiones". Es ideal si puedes formular los aspectos que no entiendes en forma de preguntas. Por lo general, necesitamos unos días para hacer mejoras.
Por cierto, tú también puedes contribuir a mejorar los cursos: en la parte inferior hay un enlace al código fuente de las lecciones, que se puede modificar directamente en el navegador.