2.11. Condicionais¶
Um condicional executa um bloco de código apenas quando um dado teste avalia como verdadeiro. A palavra-chave é if, opcionalmente seguida de um ou mais ramos elif («else if») e de um else final.
n = 42
if n > 0:
print("positive")
elif n < 0:
print("negative")
else:
print("zero")
O corpo de cada ramo é tudo o que está indentado sob ele (quatro espaços por convenção). O Python percorre os ramos em ordem, executa o primeiro cujo teste é verdadeiro e salta o resto. O bloco else só é executado se todos os testes anteriores foram falsos; é sempre opcional.
Só um ramo é executado. Os testes são avaliados de cima para baixo até um ter sucesso; os restantes são ignorados.¶
2.11.1. Veracidade¶
Um teste num if não tem de devolver True ou False – qualquer valor conta como verdadeiro ou falso. Os valores falsos são:
Tudo o resto é verdadeiro. Isto permite escrever testes compactos:
if name: # false on empty string
print("hello", name)
if items: # false on empty list, dict, etc.
process(items)
Tenha em atenção que a veracidade altera o significado. if value: não é o mesmo que if value is not None: – o primeiro também é falso quando value é 0 ou "". Quando realmente se quer dizer «isto é exatamente None«, use is None / is not None explicitamente.
2.11.2. Expressões ternárias¶
Um condicional pode aparecer dentro de uma expressão:
label = "even" if n % 2 == 0 else "odd"
Lê-se como «label é "even" se n % 2 == 0 caso contrário "odd".» Útil para linhas únicas; para qualquer coisa com mais de uma linha, uma instrução if completa é mais fácil de ler.
2.11.3. Aninhamento e retornos antecipados¶
Os condicionais podem aninhar-se arbitrariamente, mas cada camada extra de indentação torna uma função mais difícil de ler. O exemplo abaixo verifica quatro condições antes de realizar o trabalho real e deixa a linha útil enterrada quatro níveis de indentação:
def process(item):
if item is not None:
if item.is_valid():
if item.size() > 0:
if item.owner == "me":
return do_the_work(item)
return None
Dois padrões achatam este tipo de código.
2.11.3.1. Retornos antecipados para guardas¶
Trate primeiro cada caso de «saída antecipada», cada um com o seu próprio return, para que a lógica principal fique ao nível de indentação exterior. Cada guarda lê-se como «este não é um caso que tratamos; sair»:
def process(item):
if item is None:
return None
if not item.is_valid():
return None
if item.size() == 0:
return None
if item.owner != "me":
return None
return do_the_work(item)
O «caminho principal» é agora uma linha no fundo da função, não enterrada dentro de quatro camadas. Este estilo chama-se por vezes o padrão da cláusula de guarda.
2.11.3.2. Combinar testes com and / or¶
Quando várias condições têm todas de ser satisfeitas para o mesmo ramo, combine-as com and em vez de aninhar. Condições que cada uma independentemente desencadeia o ramo combinam com or:
# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
save()
# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
whitespace_count += 1
Ambas as formas fazem curto-circuito, pelo que uma verificação dispendiosa no lado direito só é executada quando as verificações mais baratas do lado esquerdo ainda não resolveram a questão.