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?

Foi útil?

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"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top