Partilhar: WhatsApp
aulify
UC UC00618 · T. Desenv. Software

Ficha 01 · Sintaxe, estruturas, funções

Variáveis, controlo, loops, funções
Versão · Aluno
Tempo · 60 minutos
Cotação · 100 pontos
Aluno(a)
Turma
Data
Objectivos da ficha

Parte I · Sintaxe e variáveis

Exercício 1 · Variáveis e tipos (10 pts)

a) Identifica o tipo de cada variável:

a = 42
b = 3.14
c = "Python"
d = True
e = None
f = [1, 2, 3]
g = (4, 5)
h = {"x": 1}
i = {1, 2, 3}

b) Que acontece em: a / 2, a // 2, a % 2, a ** 2?

a) Tipos: - a = 42int. - b = 3.14float. - c = "Python"str. - d = Truebool. - e = NoneNoneType. - f = [1, 2, 3]list. - g = (4, 5)tuple. - h = {"x": 1}dict. - i = {1, 2, 3}set.

Verificar com type(a).

b) Operações: - 42 / 2 = 21.0 (divisão sempre retorna float). - 42 // 2 = 21 (divisão inteira, int). - 42 % 2 = 0 (resto). - 42 ** 2 = 1764 (potência).

Adicionalmente: - 42 // 5 = 8 (truncado). - 42 % 5 = 2 (resto). - 2 ** 10 = 1024.

Exercício 2 · F-strings (10 pts)

Reescreve com f-string:

nome = "Ana"
idade = 25
preco = 19.99
mensagem = "Olá " + nome + ", tens " + str(idade) + " anos. O preço é " + str(preco) + " euros."

Reescrito com f-string:

nome = "Ana"
idade = 25
preco = 19.99

mensagem = f"Olá {nome}, tens {idade} anos. O preço é {preco} euros."

Mais polido (formatação de preço):

mensagem = f"Olá {nome}, tens {idade} anos. O preço é {preco:.2f}€."

Outras opções de formatação:

# Decimais
f"{preco:.2f}"     # '19.99'
f"{preco:.4f}"     # '19.9900'

# Padding
f"{nome:>10}"      # '       Ana' (direita, 10 chars)
f"{nome:<10}"      # 'Ana       ' (esquerda)
f"{nome:^10}"      # '   Ana    ' (centro)

# Padding com char
f"{nome:*>10}"     # '*******Ana'

# Números
f"{1234567:,}"     # '1,234,567' (separador milhares)
f"{0.5:%}"         # '50.000000%' (percentagem)
f"{0.5:.1%}"       # '50.0%'

# Hexadecimal
f"{255:x}"         # 'ff'
f"{255:X}"         # 'FF'
f"{255:#x}"        # '0xff'

# Binário
f"{10:b}"          # '1010'

# Em expressões
f"{nome.upper()}"  # 'ANA'
f"{idade * 2}"     # '50'

# Multi-linha
texto = f"""
Olá {nome},
A tua idade é {idade}.
"""

Vantagens f-strings vs alternativas: - f-string: f"{nome} tem {idade}" ✅ moderno, legível, rápido. - format: "{} tem {}".format(nome, idade) (antigo, ainda válido). - %: "%s tem %d" % (nome, idade) (muito antigo). - Concatenação: nome + " tem " + str(idade) (verbose, erro-prone).

Sempre preferir f-strings em Python 3.6+.

Parte II · Estruturas de controlo

Exercício 3 · If/Elif/Else (10 pts)

Escreve função que classifica nota numérica: - 0-9: "Reprovado" - 10-13: "Suficiente" - 14-15: "Bom" - 16-17: "Muito Bom" - 18-20: "Excelente" - Outras: "Inválido"

def classificar_nota(nota: int) -> str:
    """Classifica nota de 0-20."""
    if nota < 0 or nota > 20:
        return "Inválido"
    elif nota < 10:
        return "Reprovado"
    elif nota < 14:
        return "Suficiente"
    elif nota < 16:
        return "Bom"
    elif nota < 18:
        return "Muito Bom"
    else:
        return "Excelente"


# Testar
notas = [-1, 0, 9, 10, 13, 14, 15, 16, 17, 18, 20, 21]
for n in notas:
    print(f"{n}: {classificar_nota(n)}")

Output:

-1: Inválido
0: Reprovado
9: Reprovado
10: Suficiente
13: Suficiente
14: Bom
15: Bom
16: Muito Bom
17: Muito Bom
18: Excelente
20: Excelente
21: Inválido

Alternativa mais idiomática com match-case (Python 3.10+):

def classificar_nota(nota: int) -> str:
    match nota:
        case n if n < 0 or n > 20:
            return "Inválido"
        case n if n < 10:
            return "Reprovado"
        case n if n < 14:
            return "Suficiente"
        case n if n < 16:
            return "Bom"
        case n if n < 18:
            return "Muito Bom"
        case _:
            return "Excelente"

Alternativa com dict (elegante para muitos casos):

def classificar_nota(nota: int) -> str:
    if nota < 0 or nota > 20:
        return "Inválido"

    classificacoes = [
        (0, "Reprovado"),
        (10, "Suficiente"),
        (14, "Bom"),
        (16, "Muito Bom"),
        (18, "Excelente"),
    ]

    for limite, cat in reversed(classificacoes):
        if nota >= limite:
            return cat

Type hints + validação:

def classificar_nota(nota: int) -> str:
    if not isinstance(nota, int):
        raise TypeError("Nota deve ser inteiro")
    if not 0 <= nota <= 20:
        raise ValueError("Nota deve estar entre 0 e 20")

    # ... resto da lógica

Princípio: para esta lógica simples, primeira versão (if/elif/else) é clara e legível.

Exercício 4 · Loops (15 pts)

a) Escreve loop que imprime números pares de 0 a 20. b) Conta vogais numa string. c) FizzBuzz: imprime 1 a 30. Se múltiplo de 3, "Fizz". Se múltiplo de 5, "Buzz". Se ambos, "FizzBuzz".

a) Números pares de 0 a 20:

# Solução 1: for + if
for i in range(21):
    if i % 2 == 0:
        print(i)

# Solução 2: range com step
for i in range(0, 21, 2):
    print(i)

# Solução 3: list comprehension
pares = [i for i in range(21) if i % 2 == 0]
print(pares)

Solução 2 é mais Pythonic (sem condição desnecessária).


b) Contar vogais:

def contar_vogais(texto: str) -> int:
    """Conta vogais (incluindo acentuadas)."""
    vogais = "aeiouáéíóúàèìòùâêîôûãõ"
    contador = 0

    for char in texto.lower():
        if char in vogais:
            contador += 1

    return contador


# Testar
print(contar_vogais("Olá, mundo!"))     # 4 (O, á, u, o)
print(contar_vogais("Python"))           # 1 (o)
print(contar_vogais("AEIOU"))            # 5

Solução mais Pythonic com sum:

def contar_vogais(texto: str) -> int:
    vogais = "aeiouáéíóúàèìòùâêîôûãõ"
    return sum(1 for char in texto.lower() if char in vogais)

Com Counter:

from collections import Counter

def contar_vogais(texto: str) -> int:
    vogais = set("aeiouáéíóúàèìòùâêîôûãõ")
    contador = Counter(texto.lower())
    return sum(qty for char, qty in contador.items() if char in vogais)

c) FizzBuzz — clássico de entrevista:

for i in range(1, 31):
    if i % 15 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)

Output:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
...
30

Versão mais elegante:

for i in range(1, 31):
    output = ""
    if i % 3 == 0:
        output += "Fizz"
    if i % 5 == 0:
        output += "Buzz"
    print(output or i)

Truque: output or i retorna i se output é vazio (falsy).

Versão funcional:

def fizzbuzz(n):
    return "FizzBuzz" if n % 15 == 0 else \
           "Fizz" if n % 3 == 0 else \
           "Buzz" if n % 5 == 0 else \
           n

for i in range(1, 31):
    print(fizzbuzz(i))

Por que FizzBuzz em entrevistas: - Filtra candidatos que não sabem fazer básico. - Avalia: lógica, syntax, estilo. - 5 minutos chega para fazer.

Parte III · Funções

Exercício 5 · Funções (15 pts)

a) Escreve função que calcula IMC (peso/altura²). b) Adapta para receber lista de pessoas e retornar dict com IMC de cada. c) Adiciona validação de inputs.

a) Função básica:

def calcular_imc(peso: float, altura: float) -> float:
    """Calcula IMC."""
    return peso / (altura ** 2)


# Testar
print(calcular_imc(70, 1.75))  # 22.857...

b) Para lista de pessoas:

def calcular_imc(peso: float, altura: float) -> float:
    return peso / (altura ** 2)


def imcs_pessoas(pessoas: list) -> dict:
    """
    Calcula IMC para lista de pessoas.

    Args:
        pessoas: lista de dicts com 'nome', 'peso', 'altura'.

    Returns:
        Dict nome → IMC.
    """
    return {p["nome"]: calcular_imc(p["peso"], p["altura"]) for p in pessoas}


# Testar
pessoas = [
    {"nome": "Ana", "peso": 65, "altura": 1.65},
    {"nome": "João", "peso": 80, "altura": 1.80},
    {"nome": "Maria", "peso": 55, "altura": 1.60},
]

resultados = imcs_pessoas(pessoas)
for nome, imc in resultados.items():
    print(f"{nome}: {imc:.2f}")

# Ana: 23.88
# João: 24.69
# Maria: 21.48

c) Com validação completa:

def calcular_imc(peso: float, altura: float) -> float:
    """
    Calcula IMC com validação.

    Args:
        peso: kg, > 0.
        altura: metros, > 0.

    Returns:
        IMC.

    Raises:
        TypeError: se inputs não forem números.
        ValueError: se inputs não forem positivos.
    """
    # Type check
    if not isinstance(peso, (int, float)):
        raise TypeError(f"Peso deve ser número, recebeu {type(peso).__name__}")
    if not isinstance(altura, (int, float)):
        raise TypeError(f"Altura deve ser número, recebeu {type(altura).__name__}")

    # Value check
    if peso <= 0:
        raise ValueError(f"Peso deve ser positivo, recebeu {peso}")
    if altura <= 0:
        raise ValueError(f"Altura deve ser positiva, recebeu {altura}")

    # Sanidade (não obrigatório mas útil)
    if peso > 500:
        raise ValueError(f"Peso de {peso}kg é irrealista")
    if altura > 3:
        raise ValueError(f"Altura de {altura}m é irrealista")

    return peso / (altura ** 2)


def imcs_pessoas(pessoas: list) -> dict:
    """Calcula IMC para lista de pessoas, com tratamento de erros."""
    resultados = {}

    for p in pessoas:
        try:
            imc = calcular_imc(p["peso"], p["altura"])
            resultados[p["nome"]] = imc
        except (TypeError, ValueError) as e:
            print(f"Erro com {p.get('nome', '?')}: {e}")
            resultados[p["nome"]] = None
        except KeyError as e:
            print(f"Dados em falta: {e}")

    return resultados


# Testar
pessoas = [
    {"nome": "Ana", "peso": 65, "altura": 1.65},
    {"nome": "Erro1", "peso": -10, "altura": 1.70},  # peso negativo
    {"nome": "Erro2", "peso": "muito", "altura": 1.70},  # tipo errado
    {"nome": "Sem peso"},  # falta key
]

resultados = imcs_pessoas(pessoas)
for nome, imc in resultados.items():
    if imc:
        print(f"{nome}: {imc:.2f}")
    else:
        print(f"{nome}: inválido")

Output:

Erro com Erro1: Peso deve ser positivo, recebeu -10
Erro com Erro2: Peso deve ser número, recebeu str
Dados em falta: 'peso'
Ana: 23.88
Erro1: inválido
Erro2: inválido

Boas práticas demonstradas:

  1. Type hints (peso: float).
  2. Docstrings completas (description, args, returns, raises).
  3. Validação de tipos com isinstance.
  4. Validação de valores (positivo, sanidade).
  5. Mensagens de erro descritivas.
  6. Tratamento de erros no caller.
  7. Específico (TypeError vs ValueError vs KeyError).

Versão com classificação:

def classificar_imc(imc: float) -> str:
    """Classifica IMC segundo OMS."""
    if imc < 18.5:
        return "Abaixo do peso"
    elif imc < 25:
        return "Peso normal"
    elif imc < 30:
        return "Excesso de peso"
    elif imc < 35:
        return "Obesidade grau I"
    elif imc < 40:
        return "Obesidade grau II"
    else:
        return "Obesidade grau III"


# Combinar
imc = calcular_imc(70, 1.75)
print(f"IMC: {imc:.2f} ({classificar_imc(imc)})")
# IMC: 22.86 (Peso normal)

Parte IV · Estruturas de dados

Exercício 6 · Listas e dicts (15 pts)

Tens lista de produtos:

produtos = [
    {"nome": "Caneta", "preco": 1.50, "stock": 50},
    {"nome": "Caderno", "preco": 3.00, "stock": 20},
    {"nome": "Lápis", "preco": 0.50, "stock": 100},
    {"nome": "Borracha", "preco": 1.00, "stock": 30},
]

a) Total em stock (€). b) Produtos com stock < 30. c) Produto mais caro. d) Ordenar por preço descendente. e) Adicionar 10% IVA a todos os preços.

produtos = [
    {"nome": "Caneta", "preco": 1.50, "stock": 50},
    {"nome": "Caderno", "preco": 3.00, "stock": 20},
    {"nome": "Lápis", "preco": 0.50, "stock": 100},
    {"nome": "Borracha", "preco": 1.00, "stock": 30},
]

a) Total em stock (€):

# Solução 1: loop tradicional
total = 0
for p in produtos:
    total += p["preco"] * p["stock"]
print(f"Total: {total}€")

# Solução 2: sum + generator (idiomática)
total = sum(p["preco"] * p["stock"] for p in produtos)
print(f"Total: {total}€")
# Total: 235.0€

b) Produtos com stock < 30:

# List comprehension
baixo_stock = [p for p in produtos if p["stock"] < 30]
print(baixo_stock)
# [{'nome': 'Caderno', 'preco': 3.0, 'stock': 20}]

# Apenas nomes
nomes_baixo = [p["nome"] for p in produtos if p["stock"] < 30]
print(nomes_baixo)
# ['Caderno']

# Com filter (alternativa funcional)
baixo_stock = list(filter(lambda p: p["stock"] < 30, produtos))

c) Produto mais caro:

# Solução 1: max com key
mais_caro = max(produtos, key=lambda p: p["preco"])
print(mais_caro)
# {'nome': 'Caderno', 'preco': 3.0, 'stock': 20}

# Solução 2: sorted (mais info)
ordenados = sorted(produtos, key=lambda p: p["preco"], reverse=True)
mais_caro = ordenados[0]

# Solução 3: max + iter (apenas nome)
nome_mais_caro = max(produtos, key=lambda p: p["preco"])["nome"]
print(nome_mais_caro)
# Caderno

d) Ordenar por preço descendente:

# Não modifica original
ordenados = sorted(produtos, key=lambda p: p["preco"], reverse=True)

# Modifica original
produtos.sort(key=lambda p: p["preco"], reverse=True)

print(ordenados)
# [
#   {'nome': 'Caderno', 'preco': 3.0, 'stock': 20},
#   {'nome': 'Caneta', 'preco': 1.5, 'stock': 50},
#   {'nome': 'Borracha', 'preco': 1.0, 'stock': 30},
#   {'nome': 'Lápis', 'preco': 0.5, 'stock': 100}
# ]

Ordenar por múltiplos critérios (preço desc, depois stock asc):

ordenados = sorted(produtos, key=lambda p: (-p["preco"], p["stock"]))

e) Adicionar 10% IVA:

Modificar in-place:

for p in produtos:
    p["preco"] = round(p["preco"] * 1.10, 2)

print(produtos)
# [{'nome': 'Caneta', 'preco': 1.65, 'stock': 50}, ...]

Criar nova lista (não mexer original):

com_iva = [
    {**p, "preco": round(p["preco"] * 1.10, 2)}
    for p in produtos
]

Operador **: spread/unpack dict. {**p, "preco": novo} copia todos os pares de p mas substitui preco.

Solução completa com funções:

def total_em_stock(produtos: list) -> float:
    """Calcula valor total em stock."""
    return sum(p["preco"] * p["stock"] for p in produtos)


def filtrar_baixo_stock(produtos: list, limite: int = 30) -> list:
    """Retorna produtos com stock abaixo do limite."""
    return [p for p in produtos if p["stock"] < limite]


def produto_mais_caro(produtos: list) -> dict:
    """Retorna produto com maior preço."""
    return max(produtos, key=lambda p: p["preco"])


def ordenar_por_preco(produtos: list, reverse: bool = True) -> list:
    """Ordena produtos por preço."""
    return sorted(produtos, key=lambda p: p["preco"], reverse=reverse)


def aplicar_iva(produtos: list, taxa: float = 0.23) -> list:
    """Aplica IVA aos preços (sem modificar original)."""
    return [
        {**p, "preco_com_iva": round(p["preco"] * (1 + taxa), 2)}
        for p in produtos
    ]


# Usar
print(f"Total em stock: {total_em_stock(produtos):.2f}€")
print(f"Baixo stock: {filtrar_baixo_stock(produtos)}")
print(f"Mais caro: {produto_mais_caro(produtos)['nome']}")
print(f"Ordenados: {ordenar_por_preco(produtos)}")
print(f"Com IVA: {aplicar_iva(produtos)}")

Princípios aplicados: - List comprehensions (idiomáticas). - Sum + generator (memory efficient). - Max/min com key (elegante). - Sorted vs sort (consciência de side effects). - Funções pequenas e reutilizáveis. - Type hints + docstrings.

Parte V · Aplicação

Exercício 7 · Refactor (10 pts)

Refactoriza este código para ser mais Pythonic:

def processar(numeros):
    pares = []
    for i in range(len(numeros)):
        if numeros[i] % 2 == 0:
            pares.append(numeros[i] * 2)

    soma = 0
    for j in range(len(pares)):
        soma = soma + pares[j]

    if soma > 100:
        return "alto"
    else:
        if soma > 50:
            return "medio"
        else:
            return "baixo"

Refactor Pythonic:

def processar(numeros: list[int]) -> str:
    """Classifica soma do dobro dos pares."""
    pares_dobrados = [n * 2 for n in numeros if n % 2 == 0]
    soma = sum(pares_dobrados)

    if soma > 100:
        return "alto"
    elif soma > 50:
        return "medio"
    return "baixo"

Comparação:

Original Refactored
16 linhas 6 linhas
range(len(...)) (não-Pythonic) List comprehension
Loop manual para sum sum() built-in
Nested if/else elif chain
Sem type hints Type hints
Sem docstring Docstring

Princípios Pythonic aplicados:

  1. Iterar directamente (não com índice):
  2. for i in range(len(lista)): lista[i]
  3. for item in lista

  4. List comprehension em vez de append loop:

  5. result = []; for x in lst: if cond: result.append(...)
  6. result = [... for x in lst if cond]

  7. Built-ins (sum, max, etc.) em vez de loop manual.

  8. elif chain em vez de nested else.

  9. Return early (sem else final).

  10. Type hints para clareza.

  11. Docstring mesmo em funções simples.

Versão ainda mais funcional:

def processar(numeros: list[int]) -> str:
    soma = sum(n * 2 for n in numeros if n % 2 == 0)

    return (
        "alto" if soma > 100
        else "medio" if soma > 50
        else "baixo"
    )

Generator expression (( ) em vez de [ ]): - Não cria lista intermediária na memória. - Mais eficiente para grandes inputs. - Sintaxe quase idêntica.

Em vez de:

soma = sum([n * 2 for n in numeros if n % 2 == 0])  # lista temporária

Fazer:

soma = sum(n * 2 for n in numeros if n % 2 == 0)    # generator (sem [])

Princípios Pythonic:

Quando NÃO refactor para list comprehension:

❌ Lógica complexa:

# Não fazer
result = [process(x) if cond1(x) else (other(x) if cond2(x) else None) for x in lst if filter_cond(x)]

# Fazer
result = []
for x in lst:
    if not filter_cond(x):
        continue
    if cond1(x):
        result.append(process(x))
    elif cond2(x):
        result.append(other(x))
    else:
        result.append(None)

Regra: list comprehension legível em uma linha. Se não cabe, usar loop tradicional.

Exercício 8 · Programa completo (15 pts)

Escreve programa que: 1. Pede ao utilizador 5 números. 2. Calcula min, max, média. 3. Identifica números primos. 4. Imprime resultado formatado.

def é_primo(n: int) -> bool:
    """Verifica se n é primo."""
    if n < 2:
        return False
    if n == 2:
        return True
    if n % 2 == 0:
        return False

    # Verificar apenas até sqrt(n)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if n % i == 0:
            return False
    return True


def pedir_numeros(quantidade: int = 5) -> list[int]:
    """Pede ao utilizador quantidade números."""
    numeros = []
    print(f"Insere {quantidade} números:")

    while len(numeros) < quantidade:
        try:
            entrada = input(f"Número {len(numeros) + 1}: ")
            numero = int(entrada)
            numeros.append(numero)
        except ValueError:
            print("⚠️  Não é número inteiro. Tenta novamente.")

    return numeros


def analisar(numeros: list[int]) -> dict:
    """Calcula estatísticas e identifica primos."""
    return {
        "numeros": numeros,
        "min": min(numeros),
        "max": max(numeros),
        "media": sum(numeros) / len(numeros),
        "primos": [n for n in numeros if é_primo(n)],
        "soma": sum(numeros),
    }


def imprimir_relatorio(analise: dict) -> None:
    """Imprime relatório formatado."""
    print("\n" + "=" * 40)
    print("📊 RELATÓRIO DE ANÁLISE")
    print("=" * 40)

    print(f"\nNúmeros: {analise['numeros']}")
    print(f"\n📉 Mínimo:  {analise['min']}")
    print(f"📈 Máximo:  {analise['max']}")
    print(f"➕ Soma:    {analise['soma']}")
    print(f"📊 Média:   {analise['media']:.2f}")

    if analise['primos']:
        print(f"\n🔢 Primos:  {analise['primos']}")
        print(f"   (Encontrados {len(analise['primos'])} primos)")
    else:
        print(f"\n🔢 Primos:  (nenhum)")

    print("=" * 40)


def main():
    """Programa principal."""
    print("🔢 ANALISADOR DE NÚMEROS")
    print("-" * 40)

    try:
        numeros = pedir_numeros(5)
        analise = analisar(numeros)
        imprimir_relatorio(analise)
    except KeyboardInterrupt:
        print("\n\n👋 Programa cancelado.")
    except Exception as e:
        print(f"\n❌ Erro: {e}")


if __name__ == "__main__":
    main()

Exemplo de execução:

🔢 ANALISADOR DE NÚMEROS
----------------------------------------
Insere 5 números:
Número 1: 7
Número 2: 13
Número 3: 4
Número 4: abc
⚠️  Não é número inteiro. Tenta novamente.
Número 4: 11
Número 5: 20

========================================
📊 RELATÓRIO DE ANÁLISE
========================================

Números: [7, 13, 4, 11, 20]

📉 Mínimo:  4
📈 Máximo:  20
➕ Soma:    55
📊 Média:   11.00

🔢 Primos:  [7, 13, 11]
   (Encontrados 3 primos)
========================================

Princípios aplicados:

  1. Funções pequenas com responsabilidade única:
  2. é_primo(): testa primalidade.
  3. pedir_numeros(): interage com utilizador.
  4. analisar(): calcula.
  5. imprimir_relatorio(): apresenta.
  6. main(): orquestra.

  7. Type hints em todas as funções.

  8. Docstrings descritivas.

  9. Tratamento de erros:

  10. try/except em input.
  11. KeyboardInterrupt para Ctrl+C.
  12. Genérico para safety.

  13. Algoritmo eficiente para primo:

  14. Casos especiais primeiro (< 2, == 2).
  15. Apenas até sqrt(n).
  16. Apenas números ímpares.

  17. if __name__ == "__main__": — permite importar sem executar.

  18. Output bonito com emojis e formatação.

Extensões possíveis:

Versão melhorada com argparse:

import argparse

def main():
    parser = argparse.ArgumentParser(description="Analisador de números")
    parser.add_argument("--quantidade", "-q", type=int, default=5,
                       help="Quantos números a analisar")
    parser.add_argument("--ficheiro", "-f", help="Ler de ficheiro")
    args = parser.parse_args()

    if args.ficheiro:
        with open(args.ficheiro) as f:
            numeros = [int(line.strip()) for line in f]
    else:
        numeros = pedir_numeros(args.quantidade)

    analise = analisar(numeros)
    imprimir_relatorio(analise)

Correr:

python analisador.py --quantidade 10
python analisador.py --ficheiro numeros.txt