# Condições e ciclos

Decidir com if, seguir while e for, usar range e justificar a terminação.

Página: https://resumos.rgo.pt/cadeiras/ct-iadp/condicoes-ciclos/

Uma condição escolhe um caminho. Um ciclo repete instruções. Para prever a saída, segue os valores das variáveis e identifica o momento em que a condição é avaliada.

## Escolher um ramo

```
if nota >= 18:
    classificacao = "excelente"
elif nota >= 10:
    classificacao = "aprovado"
else:
    classificacao = "reprovado"
```

Python testa os ramos por ordem e executa apenas o primeiro verdadeiro. Para `nota = 19`, não volta a executar o ramo de aprovação. Dois `if` independentes seriam duas decisões, que podem executar ambas.

A indentação define o bloco. Usa quatro espaços e alinha as instruções que pertencem à mesma decisão. Uma instrução sem indentação depois do bloco executa independentemente do ramo escolhido.

`<`, `<=`, `>`, `>=`, `==` e `!=` comparam valores. `and`, `or` e `not` combinam condições. Em `divisor != 0 and numerador / divisor > 2`, Python só divide quando a primeira condição é verdadeira. Isto chama-se **avaliação em curto-circuito**.

`0`, strings vazias, coleções vazias e `None` são falsos numa condição. Uma string `"False"` é verdadeira porque não está vazia. Usa `is None` para testar ausência e `==` para comparar valores.

## Repetir enquanto uma condição vale

Num `while`, a condição é testada antes de cada iteração. Pode não haver nenhuma iteração. Vamos somar 1, 2 e 3:

```python
k = 1
total = 0
while k <= 3:
    total += k
    k += 1
print(total)
```

| Teste antes da iteração | `k` | `total` antes | `total` depois |
| --- | --- | --- | --- |
| `1 <= 3` | 1 | 0 | 1 |
| `2 <= 3` | 2 | 1 | 3 |
| `3 <= 3` | 3 | 3 | 6 |
| `4 <= 3` | 4 | 6 | Não executa |

O resultado é 6. O ciclo termina porque `k` aumenta e acaba por ultrapassar 3. Se retirarmos `k += 1`, a condição continua verdadeira e o ciclo não termina.

![O ciclo testa k antes da soma, atualiza total e k, volta ao teste e termina quando k chega a quatro.](https://resumos.rgo.pt/cadeiras/ct-iadp/condicoes-ciclos/figura-1.svg)

## Percorrer valores com for

`for` recebe um iterável e percorre os seus elementos. Não precisas de controlar o avanço manualmente.

```
for quantidade in [2, 4, 6]:
    print(quantidade)
```

`range(inicio, fim, passo)` produz inteiros. Inclui o início e exclui o fim. O passo por defeito é 1 e não pode ser zero.

| Expressão | Valores |
| --- | --- |
| `range(4)` | 0, 1, 2, 3 |
| `range(1, 4)` | 1, 2, 3 |
| `range(2, 8, 2)` | 2, 4, 6 |
| `range(5, 0, -2)` | 5, 3, 1 |
| `range(3, 3)` | Nenhum |

Para somar de 1 até `n` inclusive, escreve `range(1, n + 1)`. Se o início já está além do fim na direção do passo, o intervalo é vazio.

## Acumular, contar e procurar

O estado inicial depende da operação: uma soma começa em zero, um produto em um. Uma contagem começa em zero e aumenta apenas quando a condição se verifica.

```python
valores = [3, -1, 4, 0, 2]
total = 0
contagem = 0
for valor in valores:
    if valor > 0:
        total += valor
        contagem += 1
print(total, contagem)
print(total / contagem)
```

A saída é `9 3`, seguida de `3.0`. A média usa três observações, não o comprimento da lista inteira. Se não houver positivos, a contagem é zero e a divisão precisa de um ramo que trate esse caso.

`break` termina o ciclo mais próximo. `continue` passa ao próximo teste ou próximo elemento. Um `else` de um ciclo executa quando o ciclo acaba normalmente, sem `break`, e não significa que a última condição de um `if` foi falsa.

## Ciclos dentro de ciclos

Para uma tabela com duas linhas e três colunas, o ciclo exterior escolhe a linha e o interior percorre as suas colunas. Há seis visitas a células. Se `break` estiver no ciclo interior, sai apenas desse ciclo. Não alteres a coleção que estás a percorrer sem compreender como isso muda os elementos que o iterador ainda vai visitar.

## Exercícios

Contar iterações

Qual é a soma dos valores de range(2, 9, 2)?

Primeira pista

O limite 9 não é incluído.

Mais uma pista

Enumera 2, 4, 6 e 8.

Ver solução

A soma é 2 + 4 + 6 + 8 = 20. Há quatro iterações.

#### Erros frequentes

Incluir 9 ou 10, ou confundir quatro iterações com quatro unidades.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/condicoes-ciclos/#percorrer-valores-com-for)

Seguir o estado

Começa com x = 1 e total = 0. Enquanto x menor que 5, soma x a total e duplica x. Quanto vale total no fim?

Primeira pista

A atualização de x acontece depois da soma.

Mais uma pista

Os valores somados são 1, 2 e 4; o teste seguinte usa 8.

Ver solução

O total é 7. O ciclo termina quando x chega a 8, porque 8 não é menor que 5.

#### Erros frequentes

Somar 8 antes de testar a condição ou incrementar x em vez de o duplicar.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/condicoes-ciclos/#repetir-enquanto-uma-condi%C3%A7%C3%A3o-vale)

Tratar o caso sem positivos

Completa a função para devolver a média dos valores estritamente positivos ou None quando não existem. Mantém os resultados esperados.

```python
def media_positivos(valores):
    return None

assert media_positivos([3, -1, 4, 0, 2]) == 3
assert media_positivos([]) is None
assert media_positivos([-2, 0]) is None
print("Casos verificados")
```

Primeira pista

Acumula soma e contagem apenas quando o valor é maior que zero.

Mais uma pista

Se a contagem for zero, devolve None antes de dividir.

Ver solução

Inicializa soma e contagem a zero; percorre os valores e atualiza ambas para positivos. Rejeita a divisão quando a contagem é zero.

Confere a tua resposta:

*   Devolve 3 para \[3, -1, 4, 0, 2\].
*   Devolve None para \[\] e \[-2, 0\].
*   Explico por que o denominador conta apenas valores positivos.

#### Erros frequentes

Dividir pelo comprimento original, contar zero como positivo ou inventar média zero para a ausência de dados.

[Voltar à explicação](https://resumos.rgo.pt/cadeiras/ct-iadp/condicoes-ciclos/#acumular-contar-e-procurar)
