Pular para conteúdo

Lista 13 · Decompor e testar

A última lista do semestre. O formato é o mesmo da Lista 12 — função com testes prontos no fim do arquivo —, mas alguns exercícios agora pedem duas funções no mesmo arquivo, uma chamando a outra: é a decomposição do Capítulo 13.

Lembre-se do escopo: uma variável criada dentro de uma função não existe fora dela — quem quiser usar o resultado precisa do return. E, se um teste falhar, o AssertionError aponta a linha exata; leia com calma antes de mexer na função.

Abrir no Colab

Baixar o caderno

Como esta lista funciona

Abra o caderno no Colab e salve uma cópia no seu Drive antes de começar (Arquivo → Salvar uma cópia no Drive). Sem isso, você perde o que escrever.

Nos exercícios com célula de teste, escreva a solução no lugar do # TODO e rode a célula de teste logo abaixo. Ela mesma diz o que passou e o que falhou; se aparecer AssertionError, a linha apontada é o caso que a sua solução ainda não atende. Não altere a célula de teste.

O código de cada exercício também está aqui embaixo, caso você prefira colar num editor local.

Parte A · no papel

Faça esta parte antes de ligar o computador

Escreva a resposta no caderno, depois rode para conferir. Prever e errar ensina; rodar primeiro e ler a saída, não.

No papel, antes do computador.

A1. Rastreie as funções. Complete a tabela com o que cada chamada devolve.

def calcula_desconto(preco, percentual):
    return preco * percentual / 100


def preco_final(preco, percentual):
    desconto = calcula_desconto(preco, percentual)
    return preco - desconto


preco_final(200, 10)
Chamada Devolve
calcula_desconto(200, 10)
preco_final(200, 10)

A2. Escopo. O que este programa imprime, ou qual erro ele dá? Justifique em uma frase.

def calcula_desconto(preco, percentual):
    desconto = preco * percentual / 100
    return desconto


calcula_desconto(200, 10)
print(desconto)

A3. Passa ou falha? Para cada assert abaixo, diga se ele passa em silêncio ou levanta AssertionError. Use esta função:

def dobro(numero):
    return numero * 2
Assert Passa ou falha?
assert dobro(4) == 8
assert dobro(0) == 0
assert dobro(4) == 9
assert dobro(-2) == -4

A4. Ache o defeito. Estas duas funções deveriam trabalhar juntas, mas preco_final está errado — e o teste de calcula_desconto, sozinha, passaria sem denunciar nada. Qual é o defeito?

def calcula_desconto(preco, percentual):
    return preco * percentual / 100


def preco_final(preco, percentual):
    return preco - (preco * 10 / 100)

Parte B · no computador

Exercício 01

Uma loja paga um bônus fixo de R$ 100 ao vendedor que atinge a meta do mês.

Escreva a função bonus_por_desempenho, que recebe o total vendido e a meta e devolve 100.0 se a meta foi atingida (ou superada), e 0.0 caso contrário.

bonus_por_desempenho(120, 100)  # -> 100.0
bonus_por_desempenho(90, 100)   # -> 0.0
def bonus_por_desempenho(vendas, meta):
    """Devolve 100.0 se as vendas atingirem a meta, senão 0.0."""
    # TODO: compare vendas com meta e devolva 100.0 ou 0.0
    pass


# --- testes (não altere) ---
assert bonus_por_desempenho(120, 100) == 100.0
assert bonus_por_desempenho(100, 100) == 100.0
assert bonus_por_desempenho(0, 100) == 0.0
assert bonus_por_desempenho(99, 100) == 0.0
print("Exercício 01: todos os testes passaram!")

Exercício 02

Escreva a função pacote_ultrapassado, que recebe quanto o cliente consumiu de dados no mês e o tamanho do pacote contratado (ambos em GB) e devolve True se o consumo passou do pacote, e False caso contrário.

pacote_ultrapassado(15, 10)  # -> True
pacote_ultrapassado(10, 10)  # -> False   (exatamente no limite não é "passar")
def pacote_ultrapassado(gb_usado, gb_pacote):
    """Devolve True se o consumo passou do pacote contratado."""
    # TODO: devolva o resultado da comparação de gb_usado com gb_pacote
    pass


# --- testes (não altere) ---
assert pacote_ultrapassado(15, 10) == True
assert pacote_ultrapassado(10, 10) == False
assert pacote_ultrapassado(0, 10) == False
assert pacote_ultrapassado(9.5, 10) == False
print("Exercício 02: todos os testes passaram!")

Exercício 03

Um empréstimo cobra juros simples sobre o valor emprestado.

Escreva duas funções neste arquivo. A primeira, calcula_juros, recebe o valor emprestado e a taxa de juros (em %) e devolve o valor dos juros, arredondado para duas casas. A segunda, valor_com_juros, recebe os mesmos dois parâmetros e devolve o valor total a pagar — chamando calcula_juros por dentro, em vez de repetir a conta.

calcula_juros(1000, 2)     # -> 20.0
valor_com_juros(1000, 2)   # -> 1020.0

Dica: valor_com_juros não recalcula os juros na mão — ela chama calcula_juros(valor, taxa) e soma o resultado a valor.

def calcula_juros(valor, taxa):
    """Devolve o valor dos juros (taxa em %) sobre 'valor'."""
    # TODO: multiplique valor pela taxa, divida por 100 e devolva
    # com round(..., 2)
    pass


def valor_com_juros(valor, taxa):
    """Devolve 'valor' somado aos juros calculados por calcula_juros."""
    # TODO: chame calcula_juros(valor, taxa) e some o resultado a valor
    pass


# --- testes (não altere) ---
assert calcula_juros(1000, 2) == 20.0
assert calcula_juros(1000, 0) == 0.0
assert valor_com_juros(1000, 2) == 1020.0
assert valor_com_juros(1000, 0) == 1000.0
assert valor_com_juros(0, 5) == 0.0
print("Exercício 03: todos os testes passaram!")

Exercício 04

Retome a função minutos_excedentes da Lista 12 (minutos usados menos a franquia, ou 0 se não passou) e escreva, neste mesmo arquivo, duas funções.

A primeira, minutos_excedentes, é a mesma de antes. A segunda, custo_por_excedente, recebe os minutos usados, a franquia e o preço por minuto excedente, e devolve o custo total — chamando minutos_excedentes por dentro, em vez de repetir o if.

minutos_excedentes(220, 200)          # -> 20
custo_por_excedente(220, 200, 0.50)   # -> 10.0
custo_por_excedente(200, 200, 0.50)   # -> 0.0
def minutos_excedentes(minutos_usados, minutos_franquia):
    """Devolve quantos minutos passaram da franquia, ou 0 se não passou."""
    # TODO: se minutos_usados for maior que minutos_franquia, devolva a
    # diferença; senão, devolva 0
    pass


def custo_por_excedente(minutos_usados, minutos_franquia, preco_minuto):
    """Devolve o custo dos minutos excedentes, chamando minutos_excedentes."""
    # TODO: chame minutos_excedentes(...) e multiplique pelo preco_minuto;
    # devolva com round(..., 2)
    pass


# --- testes (não altere) ---
assert minutos_excedentes(220, 200) == 20
assert minutos_excedentes(200, 200) == 0
assert custo_por_excedente(220, 200, 0.50) == 10.0
assert custo_por_excedente(200, 200, 0.50) == 0.0
assert custo_por_excedente(0, 200, 0.50) == 0.0
print("Exercício 04: todos os testes passaram!")

Exercício 05

Escreva a função resumo_conta, que recebe o nome do cliente e um valor e devolve uma única linha de texto no formato "Nome: R$ valor", sempre com duas casas decimais.

resumo_conta("Ana", 99.9)    # -> "Ana: R$ 99.90"
resumo_conta("Bruno", 0)     # -> "Bruno: R$ 0.00"

Dica: dentro de uma f-string, f"{valor:.2f}" já arredonda e completa as casas decimais.

def resumo_conta(nome_cliente, valor):
    """Devolve uma linha formatada: 'Nome: R$ valor', com duas casas."""
    # TODO: monte e devolva a f-string, com valor em duas casas decimais
    pass


# --- testes (não altere) ---
assert resumo_conta("Ana", 99.9) == "Ana: R$ 99.90"
assert resumo_conta("Bruno", 0) == "Bruno: R$ 0.00"
assert resumo_conta("Carla", 1000) == "Carla: R$ 1000.00"
assert resumo_conta("Diego", -15.5) == "Diego: R$ -15.50"
print("Exercício 05: todos os testes passaram!")

Exercício 06

Última questão do semestre — e ela reaproveita a função media que você já escreveu na Lista 12.

Escreva, neste mesmo arquivo, duas funções: media, que devolve a média aritmética de três notas (a mesma de antes); e situacao_aluno, que recebe as mesmas três notas, calcula a média chamando media por dentro e devolve a situação final:

Média Devolve
7 ou mais "aprovado"
de 5 (inclusive) até 7 (exclusive) "recuperacao"
abaixo de 5 "reprovado"
situacao_aluno(7.0, 8.0, 9.0)  # -> "aprovado"
situacao_aluno(3.0, 4.0, 5.0)  # -> "reprovado"
def media(nota1, nota2, nota3):
    """Devolve a média aritmética das três notas."""
    # TODO: some as três notas e divida o resultado por 3
    pass


def situacao_aluno(nota1, nota2, nota3):
    """Devolve 'aprovado', 'recuperacao' ou 'reprovado' a partir da média."""
    # TODO: chame media(nota1, nota2, nota3) e use if/elif/else para
    # devolver a situação, conforme a tabela do enunciado
    pass


# --- testes (não altere) ---
assert media(7.0, 8.0, 9.0) == 8.0
assert situacao_aluno(7.0, 8.0, 9.0) == "aprovado"
assert situacao_aluno(5.0, 5.0, 5.0) == "recuperacao"
assert situacao_aluno(0.0, 0.0, 0.0) == "reprovado"
assert situacao_aluno(7.0, 7.0, 7.0) == "aprovado"
print("Exercício 06: todos os testes passaram!")