Como funcionam "e" e "ou" quando combinados em uma declaração?
-
24-09-2019 - |
Pergunta
Por alguma razão, essa função me confundiu:
def protocol(port):
return port == "443" and "https://" or "http://"
Alguém pode explicar a ordem do que está acontecendo nos bastidores para fazer isso funcionar da maneira que faz.
Eu entendi assim até que tentei:
A)
def protocol(port):
if port == "443":
if bool("https://"):
return True
elif bool("http://"):
return True
return False
Ou b)
def protocol(port):
if port == "443":
return True + "https://"
else:
return True + "http://"
Isso é algum tipo de caso especial em Python, ou estou completamente entendendo mal como as declarações funcionam?
Solução
É um idioma antigo; inserindo parênteses para mostrar prioridade,
(port == "443" and "https://") or "http://"
x and y
retorna y
E se x
é verdadeiro, x
E se x
é falsamente; a or b
, vice -versa, retorna a
Se for verdadeiro, caso contrário b
.
Então se port == "443"
é verdade, isso retorna os RHs do and
, ou seja, "https://"
. Caso contrário, o and
é falso, então o or
entra em jogo e retorna `" http: // ", Está RHS.
No Python moderno, uma maneira melhor de traduzir esse idioma antigo é:
"https://" if port == "443" else "http://"
Outras dicas
and
Retorna o operando direito se a esquerda for verdadeira. or
Retorna o operando direito se a esquerda for falsa. Caso contrário, ambos retornam o operando esquerdo. Dizem que eles Coalesce.
C and X or Y
é a tentativa inicial de longa duração dos usuários do Python de proxy para C ? X : Y
Na maioria das vezes, funciona, exceto E se X
é False
- isso levou a muitos bugs no código Python, então no Perguntas frequentes em Python, você encontrará a solução mais correta sendo (C and [X] or [Y])[0]
Porque uma lista com um único elemento, independentemente de seu valor booleano avaliado, é sempre True
! Por exemplo: [None]
é True
mas None
não é. O exemplo do OP acima funciona porque a string representando X
não está vazio.
No entanto, tudo isso mudou no Python 2.5, quando o operador ternário ou condicional foi adicionado ao idioma, permitindo que você use o limpador X if C else Y
Conforme declarado em outros posts aqui. Se você vê código usando o formato mais antigo, é porque o usuário já faz um programador de Python de longa data que ainda não adotou a nova sintaxe, eles cortaram outro código antigo, ou seu empregador ainda está usando 2.4.x ( ou lançamentos anteriores), etc.
Este é um hack feio que não é recomendado. Funciona por causa do comportamento de curto-circuito de and
e or
e que eles retornam o de seus argumentos, em vez de um valor booleano. O uso dessa técnica oferece o risco de introduzir bugs difíceis de encontrar, portanto, não o use no novo código.
Aqui está um exemplo de como o and/or
O idioma pode dar um 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
Prefira a notação mais recente:
return "https://" if port == "443" else "http://"
Você pode querer ler sobre o "e / ou truque" do Python neste artigo A natureza peculiar de e / / ou em python. É um pouco como o IIF()
em VBA ou VB, ou ?:
em idiomas no estilo C.
Esta construção funciona porque 'se desenrola' para o seguinte código:
A e B ->
if a:
return b
else:
return a
a ou b ->
if a:
return a
else:
return b
Com todas as boas respostas, descobri que essas declarações me ajudam a lembrar melhor e encaixar como meu cérebro funciona (e espero que por mais um pouco por aí):
“E" retorna o primeiro item falso (por exemplo, nenhum, “", [], (), {}, 0) ou o último item se nenhum (por exemplo, nenhum false encontrado)
“Ou" retorna o primeiro item verdadeiro ou o último item (por exemplo, sem verdadeiro encontrado) **
Resumindo:
- Todos eles retornam o primeiro item que decide o resultado da declaração. (Na pior das hipóteses, o último item da sequência)
Observe que esta regra também se aplica a uma declaração acorrentada a todos "e" ou tudo "ou"