UC00607 · Programação estruturada · complexidade superior
Aulify · Componente Tecnológica

Programação estruturada · complexidade superior

Recursão, módulos, testes e estruturas mais complexas
UC00607 · 50 horas · 4,5 pontos Nível 4 · TDS · Ano 2
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Resultados de aprendizagem

  1. Resolver problemas com recursão e algoritmos clássicos.
  2. Organizar código em módulos e pacotes.
  3. Testar com unittest / pytest.
  4. Manipular dados complexos (JSON, CSV, APIs).
Continuação directa da UC00606. Os fundamentos estão dados; agora produzimos programas maiores e mais sofisticados.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Bloco 1 · Recursão

Funções que se chamam

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Princípio

def factorial(n):
    if n <= 1:           # caso base
        return 1
    return n * factorial(n - 1)  # passo recursivo

factorial(5)  # 120

Duas partes obrigatórias:

  1. Caso base — quando parar.
  2. Passo recursivo — chama com problema menor.
Sem caso base → stack overflow. Python limita recursão a ~1000 níveis por defeito.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Exemplos clássicos

def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

def somar_lista(lst):
    if not lst:
        return 0
    return lst[0] + somar_lista(lst[1:])

def reverso(s):
    if len(s) <= 1:
        return s
    return reverso(s[1:]) + s[0]
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Recursão vs iteração

A maioria dos problemas pode resolver-se das duas formas. Recursão é mais expressiva mas pode ser mais lenta e consumir mais memória.

# Iterativo
def factorial_it(n):
    r = 1
    for i in range(2, n + 1):
        r *= i
    return r

# Recursivo
def factorial_rec(n):
    return 1 if n <= 1 else n * factorial_rec(n - 1)

Recursão brilha em problemas naturalmente recursivos: árvores, ficheiros, fractais.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Bloco 2 · Algoritmos

Pesquisa e ordenação

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Pesquisa linear vs binária

Linear (O(n)): percorre tudo.

def linear(lst, alvo):
    for i, v in enumerate(lst):
        if v == alvo:
            return i
    return -1

Binária (O(log n)): requer lista ordenada.

def binaria(lst, alvo):
    lo, hi = 0, len(lst) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if lst[mid] == alvo: return mid
        elif lst[mid] < alvo: lo = mid + 1
        else: hi = mid - 1
    return -1
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Ordenação · bubble sort

def bubble(lst):
    n = len(lst)
    for i in range(n):
        for j in range(0, n - i - 1):
            if lst[j] > lst[j+1]:
                lst[j], lst[j+1] = lst[j+1], lst[j]
    return lst

O(n²) — só didáctico, lento para grandes listas.

Em produção: sorted(lst) ou lst.sort() (Timsort, O(n log n)).

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Bloco 3 · Módulos

Organizar código grande

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Módulos próprios

projecto/
├── main.py
├── utils.py
├── modelos.py
└── dados/
    └── alunos.csv
# utils.py
def saudacao(nome):
    return f"Olá, {nome}!"
# main.py
import utils
from utils import saudacao
print(utils.saudacao("Ana"))
print(saudacao("Ana"))
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Pacotes

Directoria com __init__.py torna-se um pacote.

escola/
├── __init__.py
├── alunos.py
├── professores.py
└── relatorios/
    ├── __init__.py
    └── pdf.py
from escola.alunos import Aluno
from escola.relatorios.pdf import gerar_pdf
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Bloco 4 · Dados estruturados

JSON, CSV, APIs

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

JSON

import json

# Escrever
dados = {"nome": "Ana", "notas": [15, 16, 14]}
with open("dados.json", "w") as f:
    json.dump(dados, f, indent=2)

# Ler
with open("dados.json") as f:
    dados = json.load(f)

# String ↔ dict
texto = json.dumps(dados)
obj = json.loads(texto)
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

CSV

import csv

# Ler como dicts
with open("alunos.csv", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for linha in reader:
        print(linha["nome"], linha["nota"])

# Escrever
with open("saida.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["nome", "nota"])
    writer.writeheader()
    writer.writerow({"nome": "Ana", "nota": 17})
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

APIs REST

import requests

r = requests.get("https://api.openweathermap.org/data/...")
if r.status_code == 200:
    dados = r.json()
    print(dados["main"]["temp"])
else:
    print(f"Erro {r.status_code}")

requests é o pacote padrão para HTTP em Python. Instalar: pip install requests.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Bloco 5 · Testes

Garantir que funciona

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

pytest

# calculadora.py
def somar(a, b):
    return a + b

def dividir(a, b):
    if b == 0:
        raise ValueError("Divisão por zero")
    return a / b
# test_calculadora.py
import pytest
from calculadora import somar, dividir

def test_somar():
    assert somar(2, 3) == 5
    assert somar(-1, 1) == 0

def test_dividir():
    assert dividir(10, 2) == 5
    with pytest.raises(ValueError):
        dividir(10, 0)

Correr: pytest.

Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior

Boas práticas

  • Nome test_*.py ou *_test.py.
  • Funções test_*().
  • Um teste, um asserto principal.
  • Setup/teardown com fixtures.
  • CI/CD — testes correm em cada push.
Aulify · Componente Tecnológica · Cursos Profissionais
UC00607 · Programação estruturada · complexidade superior
Aulify · UC00607 · Fim

Código testado é código que sobrevive a mudanças.

📧 geral@aulify.pt
Aulify · Componente Tecnológica · Cursos Profissionais