And y Or

Alexis Roda alexis.roda.villalonga en gmail.com
Vie Nov 2 20:29:15 CET 2007


En/na Daniel ha escrit:
> Hola chicos:
> 	No entiendo muy bien el tema de los nexos lógicos en python, sé que
> devuelve el primero sino el segundo, pero no entiendo la ventaja (o no)
> del sistema.

En python se consideran falsos el valor False, las listas y tuplas 
vacías, None, la cadena vacia y el numero 0 (puede que me deje alguno). 
Cualquier otra cosa se considera verdadera (True). En tus clases puedes 
implementar el método __nonzero__ para asignar un valor de verdad o 
falsedad a las instancias según te interese.

El operador or evalúa a verdadero si *alguno* de sus operandos es 
verdadero (según lo dicho en el primer párrafo) y el operador and evalúa 
a cierto si *todos* sus operandos son verdaderos.

Ahora bien, fíjate que en algunos casos no es necesario comprobar el 
valor de todos los operandos para determinar el valor de la expresión. 
Por ejemplo:

   [1, 2] or 0

como el primero operando es verdadero y or requiere que *algún* operando 
sea verdadero ya sabemos que la expresión será verdadera, no hace falta 
evaluar el segundo operando. De la misma forma, si algún operando en un 
and es falso sabemos de antemano que el resultado será falso.

Por el motivo que fuera (supongo que influencias de algún otro lenguaje) 
los diseñadores de python decidieron que el resultado de una operación 
booleana fuera el *valor* del último operando evaluado en lugar de True 
o False. Así:

   [1, 2] or 0     -> [1,2] que es verdadero
   0 or 2          -> 2, verdadero
   0 or []         -> [], falso
   1 and []        -> [], falso
   1 or 2 and []   -> 1, verdadero
   (1 or 2) and [] -> [], falso

etc.

En algunos casos esto te puede ahorrar algún if, pero el código resulta 
más difícil de entender en general.


 > En tal caso como sería el siguiente pseudocódigo empleando python
 > 	si (x>0 y z="pppp") entonces ....

Depende de lo que haya tras el "entonces".

En un caso tipo:

   si (x>0 y z="pppp") entonces imprime "hola"

podría traducirse por:

   if x>0 and z=="pppp" :
     print "hola"

Mientras que en:

   si (x>0 y z="pppp") entonces y=1 sino y=2

podría traducirse también por:

   y=(x>0 and z=="pppp" and 1) or 2

aprovechando las propiedades del and y del or en python.

La regla general es que solo puedes combinar expresiones (trozos de 
código que evalúen a un valor) no instrucciones arbitrarias.

En lenguajes funcionales estas construcciones son mucho mas versátiles 
que en python. El ejemplo que imprime "hola" podría traducirse en elisp 
como:

(and (> x 0)
      (string-equal z "pppp")
      (print "hola"))

mientras que en python:

   (x>0 and z=="pppp") and print "hola"

dará error de sintaxis ya que print "hola" no es una expresión 
(añadiendo paréntesis funcionaria en python3k ya que print es una 
función, pero no con otras construcciones). La otra posibilidad:

   print (x>0 and z=="pppp") and "hola"

imprimirá siempre alguna cosa, "hola" cuando la expresión sea verdadera 
y False cuando sea falsa. Lo cual no es equivalente a la codificación 
original.



En resumen, no te compliques la vida y utiliza bloques if/elif/else 
cuando hagan falta :)



Saludos
------------ próxima parte ------------
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes


Más información sobre la lista de distribución Python-es