¿Cómo funcionan “y” y “o” cuando se combinan en una statement?

Por alguna razón esta función me confundió:

def protocol(port): return port == "443" and "https://" or "http://" 

¿Alguien puede explicar el orden de lo que está sucediendo tras bambalinas para que esto funcione de la manera en que lo hace?

Lo entendí así hasta que lo probé:

O bien A)

 def protocol(port): if port == "443": if bool("https://"): return True elif bool("http://"): return True return False 

O B)

 def protocol(port): if port == "443": return True + "https://" else: return True + "http://" 

¿Es este un tipo de caso especial en Python, o estoy malinterpretando completamente cómo funcionan las declaraciones?

Es un idioma antiguo; insertando paréntesis para mostrar prioridad,

 (port == "443" and "https://") or "http://" 

x and y devuelve y si x es verdadero, x si x es falso; a or b , viceversa, devuelve a si es verdadero, de lo contrario b .

Entonces, si el port == "443" es verdadero, esto devuelve el RHS del and , es decir, "https://" . De lo contrario, el and es falso, por lo que el or entra en juego y devuelve `” http: // “, su RHS.

En Python moderno, una mejor manera de traducir este lenguaje antiguo es:

 "https://" if port == "443" else "http://" 

and devuelve el operando derecho si el izquierdo es verdadero. or devuelve el operando derecho si el izquierdo es falso. De lo contrario, ambos devuelven el operando izquierdo. Se dice que se unen .

C and X or Y es el primer bash de larga duración de los usuarios de Python para hacer proxy para C ? X : Y C ? X : Y

En la mayoría de los casos, funciona, excepto si X es False : esto ha dado lugar a muchos errores en el código Python, por lo que en las Preguntas frecuentes de Python , encontrará la solución más correcta (C and [X] or [Y])[0] porque una lista con un solo elemento, independientemente de su valor booleano evaluado, siempre es True . Por ejemplo: [None] es True pero None no lo es. El ejemplo anterior de OP funciona porque la cadena que representa X no está vacía.

Sin embargo, todo esto cambió en Python 2.5, cuando se agregó el operador ternario o condicional al idioma, lo que le permite usar el limpiador X if C else Y como se indica en otras publicaciones aquí. Si ve el código que usa el formato anterior, es porque el usuario ha sido progtwigdor de Python desde hace mucho tiempo y aún no ha adoptado la nueva syntax, cortó y pegó otro código antiguo, o su empleador sigue usando 2.4.x ( o versiones anteriores), etc.

Este es un truco feo que no se recomienda. Funciona debido al comportamiento de cortocircuito de and y or y que devuelven uno de sus argumentos en lugar de un valor booleano. El uso de esta técnica conlleva el riesgo de introducir errores difíciles de encontrar, por lo que no lo utilice en el nuevo código.

Aquí hay un ejemplo de cómo el and/or idioma puede dar un resultado inesperado:

 >>> foo = 'foobar' >>> bar = 'foobar' >>> x = 0 >>> y = 1 >>> (foo == bar) and x or y # Will this return the value of x if (foo == bar)? 1 

Prefiere en cambio la notación más nueva:

 return "https://" if port == "443" else "http://" 

Es posible que desee leer sobre el “y / o el truco” de Python en este artículo La naturaleza peculiar de And y Or en Python . Es un poco como el IIF() en VBA o VB, o ?: En lenguajes de estilo C.

Esta construcción funciona porque se “despliega” en el siguiente código:

a y b ->

 if a: return b else: return a 

a o b ->

 if a: return a else: return b 

Con todas las buenas respuestas, encontré que estas declaraciones me ayudan a recordar esto mejor y se adaptan a cómo funciona mi cerebro (y espero que haya más por ahí):

  • “Y” devuelve el primer elemento Falso (por ejemplo, Ninguno, “”, [], (), {}, 0) o el último elemento si no hay ninguno (por ejemplo, no se encontró Falso)

  • “O” devuelve el primer elemento True o el último elemento (por ejemplo, no se encontró True) **

En resumen :

  • Todos devuelven el primer elemento que decide el resultado de la statement. (En el peor de los casos, el último elemento de la secuencia)

Tenga en cuenta que esta regla también se aplica a todos los enunciados “y” o todos “o” encadenados.