Capítulo 5: Funções e Modularização#

Definindo Funções#
🎙️ Ouça a explicação sobre condicionais (if-elif-else):
Funções são blocos de código (subprogramas) reutilizáveis que executam tarefas específicas e são essenciais para a estruturação de programas em Python. Elas permitem modularizar seu código, tornando-o mais gerenciável, legível e fácil de manter. Neste capítulo, exploraremos os conceitos essenciais sobre funções, incluindo diferentes tipos de funções e boas práticas de utilização.
Para definir uma função, utilizamos a palavra reservada def. A estrutura básica de uma função inclui:
Palavra-chave
def: Indica o início da definição de uma função.Nome da função: Deve ser descritivo e seguir as convenções de nomenclatura de Python, conforme descrito na PEP 8. Use letras minúsculas com palavras separadas por underscores (convenção snake_case).
Parênteses
()contendo os parâmetros (se houver) separados por vírgulas.Dois pontos
:para terminar a linha de cabeçalho.Bloco de código indentado que constitui o corpo da função.
(Opcional)
returnpara retornar um valor da função. Se omitido, a função retornaNonepor padrão.
Exemplo simples de uma função para calcular e retornar a soma de dois números.
Compare o fluxo dos dados com a função real abaixo:
def soma2(parametro1, parametro2):
resultado = parametro1 + parametro2
return resultado
# Chamando a função
resultado = soma2(3, 4)
print(resultado)
Saída do Código:
7
Docstrings e Type Hints#
Antes de avançar no uso de funções em Python, é importante conhecer docstrings e type hints. Essas práticas são recomendadas para tornar o código mais claro, documentado e fácil de usar.
Docstrings são strings de documentação que ficam logo após a definição de uma função, classe ou módulo. Elas descrevem o que a função faz, explicam os parâmetros e informam o valor de retorno. Isso melhora a compreensão do código e permite que ferramentas de documentação capturem essas informações automaticamente. As docstrings também aparecem quando usamos a função
helpno Python, facilitando o acesso às informações sobre a função sem precisar ler o código fonte.Type hints (ou anotações de tipo) permitem especificar os tipos esperados dos parâmetros e do valor de retorno de uma função. Isso melhora a legibilidade, ajuda na identificação de inconsistências de tipo e facilita o uso de ferramentas que verificam tipos.
Exemplo de docstring e type hints:
def soma(a: float, b: float) -> float: """ Calcula a soma de dois números. Args: a (float): Primeiro número. b (float): Segundo número. Retorna: float: A soma de 'a' e 'b'. """ return a + b
Neste exemplo, estamos indicando que
aebdevem serfloat, e que a funçãosomaretorna um valorfloat. Usandohelp(soma), você verá a docstring com os detalhes dos parâmetros e do retorno.
Funções sem Retorno (Procedimentos)#
Uma função sem retorno, também conhecida como procedimento, é um bloco de código que executa uma tarefa específica, mas não retorna nenhum valor explicitamente (retorna None implicitamente). É útil quando você deseja realizar uma ação ou exibir informações sem a necessidade de obter um resultado para uso posterior.
Exemplo:
def imprimir_cabecalho(titulo: str) -> None:
"""
Imprime um cabeçalho formatado com bordas.
Args:
titulo: Texto a ser exibido no centro do cabeçalho.
"""
largura = len(titulo) + 6
print("=" * largura)
print(f"| {titulo} |")
print("=" * largura)
# Chamando a função
imprimir_cabecalho("RELATÓRIO MENSAL")
Saída do Código:
======================
| RELATÓRIO MENSAL |
======================
Repare que o type hint -> None deixa explícito que esta função existe pelo seu efeito colateral (imprimir na tela), não para devolver um valor — sinal típico de um procedimento.
Funções com Retorno#
Funções com retorno são aquelas que devolvem um valor para a parte do código que as chamou. Esse valor pode ser atribuído a variáveis ou usado em cálculos adicionais. Abaixo, apresentamos um exemplo sem valor padrão e, em seguida, um exemplo que utiliza type hints e um valor padrão.
Exemplo sem Valor Padrão:
def soma(a: float, b: float) -> float:
"""
Calcula a soma de dois números.
Args:
a: Primeiro número a ser somado.
b: Segundo número a ser somado.
Retorna:
A soma dos valores 'a' e 'b'.
"""
return a + b
# Chamando a função com argumentos
resultado = soma(3.5, 5.0)
print(f"Resultado: {resultado}")
Saída do Código:
Resultado: 8.5
Exemplo com Type Hints e Valor Padrão:
def somaP(a: float, b: float = 0.0) -> float:
"""
Calcula a soma de dois números.
Args:
a: Primeiro número a ser somado.
b: Segundo número a ser somado, padrão é 0.0.
Retorna:
A soma dos valores 'a' e 'b'.
"""
return a + b
# Chamando a função com diferentes argumentos
resultado1 = somaP(3.5, 5.0) # Dois argumentos
resultado2 = somaP(3.5) # Usando o valor padrão de b
print(f"Resultados: {resultado1}, {resultado2}")
Saída do Código:
Resultados: 8.5, 3.5
No segundo exemplo, b tem um valor padrão de 0.0, o que permite chamar a função apenas com o primeiro argumento. Isso demonstra como o uso de type hints e valores padrão facilita a flexibilidade e a clareza do código.
Parâmetros Posicionais e Nomeados (Chave-Valor)#
Python permite que funções aceitem dois tipos principais de argumentos: posicionais e nomeados (chave-valor).
Parâmetros Posicionais: São aqueles que são passados para a função na ordem em que aparecem na definição da função.
Exemplo:
def exibir_info(nome: str, idade: int) -> None: print(f"Nome: {nome}, Idade: {idade}") # Chamando a função com parâmetros posicionais exibir_info("Alice", 30)
Saída do Código:
Nome: Alice, Idade: 30
Parâmetros Nomeados (Chave-Valor): São aqueles que são passados para a função utilizando a sintaxe
chave=valor.Exemplo:
def exibir_info(nome: str, idade: int) -> None: print(f"Nome: {nome}, Idade: {idade}") # Chamando a função com parâmetros nomeados exibir_info(idade=30, nome="Alice")
Saída do Código:
Nome: Alice, Idade: 30
Funções com Múltiplos Valores de Retorno#
Em Python, uma função pode retornar múltiplos valores, o que é muito útil para obter diferentes informações de um cálculo ou processamento em uma única chamada. Isso permite retornar resultados relacionados sem a necessidade de criar estruturas mais complexas, como classes ou dicionários.
Exemplo: Retornando Dois Valores
No exemplo abaixo, a função soma_dif_valores calcula a soma e a diferença de dois números, retornando ambos os valores ao mesmo tempo.
def soma_dif_valores(a: float, b: float) -> tuple[float, float]:
"""
Calcula a soma e a diferença de dois números.
Args:
a: Primeiro número.
b: Segundo número.
Retorna:
Uma tupla contendo a soma e a diferença dos números.
"""
soma_resultado = a + b
diferenca_resultado = a - b
return soma_resultado, diferenca_resultado
# Chamando a função
soma_valores, diferenca_valores = soma_dif_valores(10, 5)
print(f"A soma é: {soma_valores}")
print(f"A diferença é: {diferenca_valores}")
Saída do Código:
A soma é: 15.0
A diferença é: 5.0
O retorno múltiplo em Python utiliza tuplas. No momento da chamada, você pode “desempacotar” os valores em variáveis distintas, facilitando o uso.
Exemplo: Retornando Valores de Tipos Diferentes
A seguir, a função analise_lista retorna a soma dos elementos de uma lista e um valor booleano indicando se todos os números são positivos.
def analise_lista(numeros: list[int]) -> tuple[int, bool]:
"""
Analisa uma lista de números inteiros.
Args:
numeros: Lista de números inteiros.
Retorna:
- A soma dos elementos.
- Um valor booleano indicando se todos os números são positivos.
"""
soma_total = sum(numeros)
# Verificando se todos os números são positivos sem usar all
todos_positivos = True
for num in numeros:
if num <= 0:
todos_positivos = False
break
return soma_total, todos_positivos
# Chamando a função
soma, positivos = analise_lista([3, -1, 5, 7, 2])
print(f"Soma dos elementos: {soma}")
print(f"Todos os elementos são positivos? {positivos}")
Saída do Código:
Soma dos elementos: 16
Todos os elementos são positivos? False
A função retorna a soma dos elementos e verifica se todos são positivos, retornando False caso algum não seja.
Funções que Recebem Outras Funções como Argumentos#
Em Python, é possível passar funções como argumentos para outras funções, o que facilita a criação de soluções flexíveis e reutilizáveis. Essa abordagem é útil para transformar, filtrar ou aplicar operações em dados.
Exemplo: Passando Funções como Argumentos
O exemplo abaixo mostra uma função que aplica uma operação, definida por outra função, a cada elemento de uma lista.
def aplicar_operacao(operacao, lista: list[int]) -> list[int]:
"""
Aplica uma operação a cada elemento de uma lista.
Args:
operacao: Função que define a operação a ser aplicada.
lista: Lista de elementos.
Retorna:
Uma nova lista com os resultados da operação aplicada.
"""
return [operacao(elemento) for elemento in lista]
# Funções para operações matemáticas
def quadrado(x: int) -> int:
return x * x
def cubo(x: int) -> int:
return x * x * x
# Aplicando a função quadrado a uma lista
numeros = [1, 2, 3, 4, 5]
resultado_quadrado = aplicar_operacao(quadrado, numeros)
print(f"O quadrado de cada número na lista é: {resultado_quadrado}")
# Aplicando a função cubo a uma lista
resultado_cubo = aplicar_operacao(cubo, numeros)
print(f"O cubo de cada número na lista é: {resultado_cubo}")
Saída do Código:
O quadrado de cada número na lista é: [1, 4, 9, 16, 25]
O cubo de cada número na lista é: [1, 8, 27, 64, 125]
A função
aplicar_operacaorecebe:Uma função (
operacao) que define a lógica de transformação.Uma lista (
lista) cujos elementos serão processados.
Usamos uma compreensão de lista para aplicar a operação a cada elemento da lista.
As funções
quadradoecubosão exemplos de operações que podem ser passadas paraaplicar_operacao.
Esse modelo permite reutilizar o mesmo código para diferentes operações, simplificando a criação de soluções modulares e flexíveis.
Funções Anônimas (Lambda)#
As funções anônimas, também conhecidas como lambdas, são funções pequenas e temporárias definidas sem um nome formal. Elas são criadas usando a palavra-chave lambda seguida dos parâmetros da função, dois pontos (:) e a expressão a ser retornada.
A sintaxe básica de uma função lambda é:
lambda parâmetros: expressão
Exemplo com uma variável#
(lambda x: x * 2)(3)
Saída do Código:
6
Neste exemplo, uma função lambda que dobra um número é definida e imediatamente chamada com o valor 3. A função calcula 3 * 2 e retorna 6.
As funções lambda são úteis quando você precisa de uma função simples e de uso único, sem a necessidade de defini-la formalmente usando a palavra-chave def.
Exemplo com duas variáveis#
soma = lambda x, y: x + y
print(f"A soma de 5 e 7 é: {soma(5, 7)}")
Saída do Código:
A soma de 5 e 7 é: 12
Aqui, a função lambda lambda x, y: x + y recebe dois parâmetros, x e y, e retorna sua soma. Ao atribuí-la à variável soma, ela pode ser chamada como uma função comum. Na última linha, o código demonstra como calcular a soma de dois valores, exibindo o resultado.
Exemplo com listas e map()#
numeros = [1, 2, 3, 4, 5]
quadrados = list(map(lambda x: x ** 2, numeros))
print(f"Os quadrados dos números {numeros} são: {quadrados}")
Saída do Código:
Os quadrados dos números [1, 2, 3, 4, 5] são: [1, 4, 9, 16, 25]
Neste exemplo, temos uma lista de números chamada numeros. Utilizamos a função map() juntamente com uma função lambda para calcular o quadrado de cada número na lista. A função lambda lambda x: x ** 2 recebe um parâmetro x e retorna o quadrado desse valor. A função map() aplica a função lambda a cada elemento da lista numeros, retornando um objeto map. Em seguida, convertemos esse objeto em uma lista usando a função list() e atribuímos o resultado à variável quadrados. Por fim, imprimimos a lista original numeros e a lista quadrados.
Exemplo com múltiplos retornos#
quadrado_e_cubo = lambda x: (x ** 2, x ** 3)
resultado = quadrado_e_cubo(5)
print(f"O quadrado e o cubo de 5 são: {resultado}")
Saída do Código:
O quadrado e o cubo de 5 são: (25, 125)
Neste exemplo, a função lambda lambda x: (x ** 2, x ** 3) recebe um parâmetro x e retorna dois valores: o quadrado e o cubo de x, dentro de uma tupla. Ao passar 5 como argumento, a função retorna a tupla (25, 125), que é impressa na tela.
As funções lambda são uma forma concisa e elegante de criar funções simples e de uso único em Python, especialmente quando usadas em conjunto com funções de ordem superior, como map(), filter() e reduce(). Além disso, sua flexibilidade permite trabalhar com múltiplas variáveis, facilitando a criação de soluções rápidas e legíveis.
Funções Recursivas#
A recursividade é uma técnica em que uma função chama a si mesma para resolver uma versão menor do mesmo problema. A cada nova chamada, o problema é reduzido a um caso mais simples, até atingir uma situação cuja resposta é conhecida de forma direta. Esse momento de parada é chamado de caso base (ou condição de parada). Sem ele, a função continuaria a se chamar indefinidamente e o programa travaria por estouro de pilha.
Toda função recursiva combina, portanto, duas partes:
Caso base: condição que encerra a recursão sem fazer nova chamada.
Caso recursivo: chamada à própria função com uma entrada menor.
Essa abordagem é especialmente útil para problemas com estrutura auto-similar, como fatorial, sequência de Fibonacci, percursos em árvores e processamento de listas. Em muitos casos, a solução recursiva resulta em um código mais curto e expressivo do que uma versão iterativa equivalente.
Exemplo: Soma de Números de 1 até N#
A soma dos números de 1 até um número n pode ser calculada recursivamente:
def soma(n: int) -> int:
"""
Soma os inteiros positivos de 1 até n.
Args:
n: Limite superior da soma.
Retorna:
A soma 1 + 2 + ... + n. Para n <= 0, retorna 0.
"""
if n <= 0: # Proteção: evita recursão infinita para valores não positivos
return 0
if n == 1: # Caso base
return 1
return n + soma(n - 1) # Caso recursivo
# Teste da função
print(soma(5))
Saída do Código:
15
A função soma(5) chama soma(4), que chama soma(3), e assim por diante, até atingir soma(1), que retorna 1. Os valores são somados de volta ao longo da cadeia de chamadas.
Representação Recursiva
A execução da função pode ser visualizada como uma pilha de chamadas:
soma(5)
|
+--> 5 + soma(4)
|
+--> 4 + soma(3)
|
+--> 3 + soma(2)
|
+--> 2 + soma(1)
|
+--> 1 (condição de parada)
Resolução acumulada na volta:
soma(1) = 1
soma(2) = 2 + soma(1) = 2 + 1 = 3
soma(3) = 3 + soma(2) = 3 + 3 = 6
soma(4) = 4 + soma(3) = 4 + 6 = 10
soma(5) = 5 + soma(4) = 5 + 10 = 15
Atenção - Limite de recursão
Cada chamada recursiva consome um espaço na pilha de execução do Python. O interpretador limita essa pilha a cerca de 1000 chamadas por padrão. Para entradas pequenas como soma(5), isso não é problema, mas tentar soma(2000) resulta em RecursionError. Para problemas muito grandes, prefira uma versão iterativa equivalente.
Exemplo: Soma de Números em um Intervalo#
Para calcular a soma dos números entre a e b:
def soma_intervalo(a: int, b: int) -> int:
"""
Soma os inteiros do intervalo [a, b], inclusive nas duas pontas.
Args:
a: Limite inferior do intervalo.
b: Limite superior do intervalo.
Retorna:
A soma a + (a+1) + ... + b. Retorna 0 se a > b.
"""
if a > b: # Proteção: intervalo inválido
return 0
if a == b: # Caso base: chegamos ao limite superior
return a
return a + soma_intervalo(a + 1, b) # Caso recursivo
# Teste da função
print(soma_intervalo(3, 7))
Saída do Código:
25
A função soma os números incrementando a até que a > b.
Exemplo: Fatorial de um Número#
O fatorial de um número n, denotado n!, é o produto de todos os inteiros positivos de 1 até n. Esse cálculo aparece naturalmente em problemas de contagem de arranjos. Por exemplo, imagine que você tem 5 livros distintos para organizar em uma prateleira: quantas ordens diferentes de arrumação existem? A resposta é exatamente 5! = 5 × 4 × 3 × 2 × 1 = 120. A lógica é intuitiva: há 5 opções para o primeiro livro, 4 para o segundo (já que um foi usado), 3 para o terceiro, e assim por diante. Essa redução em cadeia é justamente o padrão que a recursão captura de forma elegante.
def fatorial(n: int) -> int:
"""
Calcula o fatorial de n (n!).
Args:
n: Inteiro não negativo.
Retorna:
O produto 1 × 2 × ... × n. Por convenção, 0! = 1.
Retorna 0 para entradas negativas (valor inválido).
"""
if n < 0: # Proteção: fatorial não é definido para negativos
return 0
if n == 0 or n == 1: # Caso base
return 1
return n * fatorial(n - 1) # Caso recursivo
# Quantas formas existem de organizar 5 livros distintos em uma prateleira?
print(fatorial(5))
Saída do Código:
120
A função chama a si mesma com n - 1 até que n seja 0 ou 1, retornando 1. No nosso exemplo, fatorial(5) calcula 5 × fatorial(4) = 5 × 24 = 120, ou seja, existem 120 formas distintas de organizar os 5 livros na prateleira.
Nota - Por que 0! é igual a 1
Por convenção matemática, o fatorial de 0 vale 1 (e não 0). Essa definição mantém a recorrência n! = n × (n-1)! consistente para n = 1, já que 1! = 1 × 0! = 1 × 1 = 1. Ela também aparece naturalmente em fórmulas de combinatória, como o número de formas de organizar zero objetos, que é uma única forma (a vazia).
Exemplo: Soma dos Elementos de uma Lista#
A soma dos elementos de uma lista pode ser feita de forma recursiva:
def soma_lista(lista: list[int]) -> int:
"""
Soma todos os elementos de uma lista de inteiros recursivamente.
Args:
lista: Lista de números inteiros.
Retorna:
A soma dos elementos. Para uma lista vazia, retorna 0.
"""
if len(lista) == 0: # Caso base: lista vazia
return 0
return lista[0] + soma_lista(lista[1:]) # Caso recursivo
# Teste da função
lista_exemplo = [1, 2, 3, 4, 5]
print(f"A soma dos números na lista é: {soma_lista(lista_exemplo)}")
Saída do Código:
A soma dos números na lista é: 15
A função pega o primeiro elemento da lista e chama a si mesma com o restante. O processo continua até que a lista esteja vazia.
Dica - Custo do slicing em recursão
A expressão lista[1:] cria uma nova lista a cada chamada recursiva. Para uma lista de tamanho n, isso resulta em n cópias parciais ao longo da recursão, totalizando O(n²) em memória e tempo. Para listas grandes, prefira passar um índice como argumento adicional e percorrer a lista por posição, em vez de fatiar.
Vantagens e Desvantagens da Recursividade#
Vantagens |
Desvantagens |
|---|---|
Código mais curto e expressivo, próximo da definição matemática do problema. |
Cada chamada consome memória na pilha de execução (parâmetros, variáveis locais e endereço de retorno). |
Ideal para problemas com estrutura naturalmente recursiva: fatorial, Fibonacci, percursos em árvores e processamento de listas encadeadas. |
Python limita a profundidade de chamadas a cerca de 1000 por padrão ( |
Evita variáveis auxiliares e laços quando a solução é definida de forma autorreferente. |
Sem um caso base bem definido, ocorre estouro de pilha por chamadas que nunca terminam. |
A recursividade é uma ferramenta poderosa, mas deve ser usada com cuidado. Para entradas grandes, em que o número de chamadas se aproxima do limite de profundidade da pilha, uma versão iterativa do mesmo algoritmo costuma ser mais segura. Compare o fatorial recursivo já apresentado com sua versão iterativa equivalente:
def fatorial_iterativo(n: int) -> int:
"""Versão iterativa do fatorial, sem recursão."""
if n < 0:
return 0
resultado = 1
for i in range(2, n + 1):
resultado *= i
return resultado
print(fatorial_iterativo(5))
Saída do Código:
120
A versão iterativa usa apenas uma variável (resultado) e um laço, sem empilhar chamadas. Para entradas pequenas, as duas versões são intercambiáveis. Para valores grandes (por exemplo, n = 10000), a versão recursiva levanta RecursionError, enquanto a iterativa termina normalmente.
Outras Funções Built-in#
Os capítulos anteriores já apresentaram diversas funções built-in essenciais como print(), input(), conversões de tipo (int(), float(), str(), etc.), len() e range(). Esta seção apresenta outras funções built-in úteis que ainda não foram cobertas, agrupadas por categoria.
Categoria |
Função |
Descrição |
Exemplo |
Saída |
|---|---|---|---|---|
Manipulação de Sequências |
|
Retorna o valor máximo em uma sequência. |
|
|
|
Retorna o valor mínimo em uma sequência. |
|
|
|
|
Soma os elementos de uma sequência numérica. |
|
|
|
|
Retorna uma lista ordenada. |
|
|
|
|
Retorna |
|
|
|
Tipo e Valor |
|
Retorna o valor hash inteiro de um objeto. Para strings, muda a cada execução do programa. |
|
(inteiro; varia entre execuções) |
Matemática |
|
Retorna a raiz quadrada de um número. |
|
|
|
Calcula o fatorial de um número. |
|
|
|
Iteração |
|
Gera pares (índice, valor) ao iterar sobre uma sequência. |
|
|
|
Combina elementos de múltiplos iteráveis em tuplas. |
|
|
|
Outros |
|
Exibe a documentação de um objeto. |
|
(documentação do |
|
Lista os atributos e métodos de um objeto. |
|
(lista de métodos e atributos) |
|
|
Abre um arquivo e retorna um objeto de arquivo. |
|
(objeto de arquivo) |
|
|
Avalia uma expressão em forma de string. |
|
|
|
|
Executa um código Python em forma de string. |
|
(define |
Atenção - Risco de eval e exec
eval() e exec() executam código Python contido em uma string. Isso é perigoso quando a string vem de uma fonte externa (entrada do usuário, arquivo, requisição de rede), pois abre brecha para execução de código arbitrário. Por exemplo, eval(input()) permite que qualquer pessoa rode qualquer comando dentro do seu programa.
Para conversões simples de texto em número, use int(), float() ou bool(). Para avaliar literais Python de forma segura (listas, dicionários, tuplas, números), use ast.literal_eval() do módulo ast. Evite eval e exec em código real, exceto em casos muito específicos em que você controla completamente a entrada.
Observação - módulo math
As funções matemáticas como math.sqrt() e math.factorial() exigem a importação do módulo math.
Exemplo:
import math
raiz = math.sqrt(16)
print(raiz)
Saída do Código:
4.0
Documentação oficial
Para a lista completa de funções built-in e detalhes de cada uma, consulte a documentação oficial do Python.
Exercícios#
Menor e Maior entre Três Números
Desenvolva um programa que determine o menor e o maior número entre três valores fornecidos pelo usuário. O programa deve utilizar funções para realizar as operações necessárias. Siga as instruções:
Crie uma função chamada
ler_numeros()que solicite ao usuário que insira três números e retorne esses valores.Implemente uma função chamada
encontrar_menor_maior(a, b, c)que receba três números como parâmetros e retorne uma tupla contendo o menor e o maior valor, nesta ordem.No programa principal, utilize as funções criadas para:
Obter os três números do usuário.
Calcular o menor e o maior valor.
Exibir os resultados.
Exemplo de uso no programa principal:
num1, num2, num3 = ler_numeros()
menor, maior = encontrar_menor_maior(num1, num2, num3)
print(f"O menor número é: {menor}")
print(f"O maior número é: {maior}")
Certifique-se de que o programa trate adequadamente diferentes tipos de entrada, incluindo números inteiros e decimais.
# Teste 1
Entrada: 10, 5, 8
Saída:
O menor número é: 5
O maior número é: 10
# Teste 2
Entrada: 3.14, 1.71, 1.41
Saída:
O menor número é: 1.41
O maior número é: 3.14
# Teste 3
Entrada: -5, 0, -10
Saída:
O menor número é: -10
O maior número é: 0
# Teste 4
Entrada: 1, 3.14, 2
Saída:
O menor número é: 1
O maior número é: 3.14
Cálculo do IMC Utilizando Funções
Desenvolva um programa em Python para calcular o Índice de Massa Corporal (IMC) de uma pessoa, utilizando funções para organizar e modularizar o código.
O programa deve incluir as seguintes funções:
Uma função para ler os dados do usuário (peso em kg e altura em metros).
Uma função para calcular o IMC usando a fórmula: IMC = peso / (altura * altura).
Uma função para classificar o IMC de acordo com as faixas padrão.
A classificação do IMC deve seguir a tabela abaixo:
IMC (kg/m²) |
Classificação |
|---|---|
< 18.5 |
Abaixo do peso |
18.5 - 24.9 |
Peso normal |
25.0 - 29.9 |
Sobrepeso |
30.0 - 34.9 |
Obesidade grau 1 |
35.0 - 39.9 |
Obesidade grau 2 |
≥ 40.0 |
Obesidade grau 3 |
No programa principal, chame as funções na ordem adequada para:
Obter os dados do usuário.
Calcular o IMC.
Determinar a classificação.
Por exemplo:
peso, altura = ler_dados()
imc = calcular_imc(peso, altura)
classificacao = classificar_imc(imc)
print(f"Seu IMC é {imc:.2f} - Classificação: {classificacao}")
Certifique-se de tratar possíveis erros de entrada do usuário, como valores negativos ou zero para peso e altura. O programa deve ser robusto e capaz de lidar com diferentes cenários de entrada.
# Teste 1
Entrada: 90.5, 1.85
Saída: Seu IMC é 26.44 - Classificação: Sobrepeso
# Teste 2
Entrada: 65.0, 1.75
Saída: Seu IMC é 21.22 - Classificação: Peso normal
# Teste 3
Entrada: 45.0, 1.60
Saída: Seu IMC é 17.58 - Classificação: Abaixo do peso
# Teste 4
Entrada: 120.0, 1.70
Saída: Seu IMC é 41.52 - Classificação: Obesidade grau 3
Calculadora de Área de Formas Geométricas
Crie um programa que funcione como uma calculadora de área para diferentes formas geométricas, incluindo triângulo, círculo e retângulo. O programa deve fornecer um menu fácil de usar para que o usuário selecione a forma desejada e, em seguida, insira as dimensões necessárias para calcular a área.
Crie uma função principal chamada calcular_area() que representa a abstração de um menu ao usuário com as seguintes opções:
Opção 1: Calcular a área de um triângulo (base e altura)
Opção 2: Calcular a área de um círculo (raio)
Opção 3: Calcular a área de um retângulo (comprimento e largura)
Opção 4: Sair do programa
Crie individualmente uma função para o cálculo das áreas de cada forma geométrica:
area_triangulo(base, altura)area_circulo(raio)area_retangulo(comprimento, largura)
Exemplos de teste:
# Teste 1
Entrada:
1
5
10
Saída: A área do triângulo é: 25.00
# Teste 2
Entrada:
2
3
Saída: A área do círculo é: 28.27
# Teste 3
Entrada:
3
4
6
Saída: A área do retângulo é: 24.00
# Teste 4
Entrada: 4
Saída: Programa encerrado.
Observações:
Use a biblioteca
mathpara obter o π (pi) nos cálculos do círculo.Arredonde todos os resultados para duas casas decimais.
4. Sistema de Bonificação para Atletas Olímpicos
O Comitê Olímpico Nacional decidiu criar um sistema de bonificação para atletas que ganharam medalhas nas Olimpíadas. O sistema funciona da seguinte forma:
Cada atleta recebe uma bonificação base de acordo com a medalha:
Ouro: R$ 50.000
Prata: R$ 30.000
Bronze: R$ 10.000
Além disso, há bônus adicionais baseados em critérios específicos:
Quebra de recorde mundial: +R$ 100.000
Primeira medalha do país na modalidade: +R$ 50.000
Crie uma função chamada calcular_bonificacao que receba os seguintes parâmetros:
medalhas: uma lista de strings representando as medalhas ganhas (“ouro”, “prata” ou “bronze”)recorde_mundial: Uma String, Sim ou Nao, indicando se o atleta quebrou um recorde mundialprimeira_medalha_pais: Uma String, Sim ou Nao, indicando se é a primeira medalha do país na modalidade
A função deve retornar o valor total da bonificação do atleta.
# Teste 1
Entrada:Ouro,Sim,Nao
Saída: 150000
# Teste 2
Entrada:Prata,Bronze,Nao,Sim
Saída: 90000
# Teste 3
Entrada:Bronze,Bronze,Bronze,Nao,Nao
Saída: 30000
# Teste 4
Entrada:Ouro,Prata,Bronze,Nao,Sim
Saída: 140000
5. Calculando as Raízes de Equações Quadráticas
Neste exercício, você terá a oportunidade de aplicar conceitos matemáticos para resolver o problema de Bhaskara, escrevendo um código para calcular as raízes de uma equação quadrática.
Dada uma equação quadrática na forma \(Ax^2 + Bx + C = 0\), escreva um programa que leia três valores de ponto flutuante e calcule as raízes da equação usando a Fórmula de Bhaskara. Se não for possível calcular as raízes, mostre a mensagem “Impossível calcular”, caso haja uma divisão por zero ou raiz de número negativo.
\( R1 = \frac{-B + \sqrt{B^2 - 4AC}}{2A} \)
\( R2 = \frac{-B - \sqrt{B^2 - 4AC}}{2A} \)
Observações:
Se \(A\) é igual a zero, não é possível calcular as raízes.
Se o discriminante \(\Delta = B^2 - 4AC \) é negativo, não é possível calcular as raízes.
As raízes da equação devem ter 2 dígitos após o ponto decimal.
Escreva uma função para leitura dos dados, outra para verificar se é possível calcular as raízes, e uma terceira para calcular e retornar as raízes.
# Teste 1
Entrada: 10.0, 19.1, 5.2
Saída:
R1 = -0.33
R2 = -1.58
# Teste 2
Entrada: 0.0, 20.0, 5.0
Saída: Impossível calcular
# Teste 3
Entrada: 1.0, -3.0, 2.0
Saída:
R1 = 2.00
R2 = 1.00
# Teste 4
Entrada: 1.0, 2.0, 5.0
Saída: Impossível calcular
6. Contando: Pares, Ímpares, Positivos e Negativos
Escreva uma função chamada contar_pares_impares que receba uma lista de números como argumento e retorne duas variáveis: a contagem de números pares e a contagem de números ímpares na lista.
Escreva outra função chamada contar_positivos_negativos que receba a mesma lista de números como argumento e retorne duas variáveis: a contagem de números positivos e a contagem de números negativos na lista.
O programa principal deve ler uma lista de números inteiros na entrada, passar essa lista para as funções acima. Em seguida, o programa deve imprimir as contagens de números pares, ímpares, positivos e negativos, cada uma em uma linha separada.
# Teste 1
Entrada: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25
Saída:
Quantidade de números pares: 24
Quantidade de números ímpares: 26
Quantidade de números positivos: 25
Quantidade de números negativos: 25
# Teste 2
Entrada: 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74, -75
Saída:
Quantidade de números pares: 23
Quantidade de números ímpares: 23
Quantidade de números positivos: 23
Quantidade de números negativos: 23
7. Soma Recursiva de uma Lista
Escreva uma função recursiva chamada soma_recursiva que receba uma lista de números inteiros como entrada e retorne a soma de todos os elementos da lista.
Por exemplo, se a lista de entrada for [1, 2, 3, 4, 5], a função deve retornar 15 (que é a soma de todos os números na lista).
Observações:
A função
soma_recursivadeve ter uma condição base, que é quando a lista está vazia.A função deve chamar a si mesma com uma versão menor da lista, até chegar na condição base.
A função deve realizar a soma dos elementos da lista de forma recursiva.
Teste sua função com as seguintes entradas:
# Teste 1
entrada = 1, 2, 3, 4, 5, 50, 60, 70, 80, 90, 0, 1
saida = 366
# Teste 2
entrada = 10, 20, 30, 40, 50, 1, 2, 3, 4, 5, 6, 7, -15, -20
saida = 143
8. Cálculo da Sequência de Fibonacci
Imagine que você tem uma lista de números. O objetivo é calcular o n-ésimo número da sequência de Fibonacci para cada número dessa lista e imprimir a soma total desses números.
A sequência de Fibonacci é como uma escada em espiral, onde cada número é a soma dos dois anteriores. Ela começa com 0 e 1, e continua infinitamente: 0, 1, 1, 2, 3, 5, 8, 13, 21…
Para isso, você precisará criar duas funções recursivas:
A função Fibonacci: Essa função será o coração da operação. Ela receberá um número como entrada e, usando a recursão, calculará o número correspondente na sequência de Fibonacci.
A função Soma Recursiva: Essa função receberá a lista de resultados da função Fibonacci e, novamente usando a recursão, somará todos os elementos dessa lista.
No final, você imprimirá na tela a soma total de todos os números da sequência de Fibonacci calculados para cada número da lista de entrada.
Lembre-se: a recursão é como um espelho que reflete a si mesmo. A função chama a si mesma para resolver problemas menores até chegar a um ponto de parada, chamado de “condição base”. É como descer uma escada: você dá um passo de cada vez até chegar ao chão.
# Teste 1
Entrada: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
Saída: 1596
# Teste 2
Entrada: 10, 11, 9, 15, 17, 23, 13, 27, 12, 11, 22
Saída: 245637
9. Cálculo da Potência de Forma Recursiva
Escreva uma função recursiva chamada calcular_potencia que receba dois números como entrada: a base (base) e o expoente (expoente). A função deve calcular e retornar o resultado da base elevada ao expoente, sem utilizar a função math.pow() ou qualquer outra função matemática avançada, apenas operações matemáticas elementares.
Por exemplo, se a base for 2 e o expoente for 3, a função deve retornar 8 (que é o resultado de 2 elevado a 3).
Observações:
A função
calcular_potenciadeve ter uma condição base, que é quando o expoente é igual a 0.A função deve chamar a si mesma com uma versão menor do expoente, até chegar na condição base.
A função deve realizar o cálculo da potência de forma recursiva, usando apenas operações matemáticas básicas (multiplicação, divisão, adição e subtração).
Teste sua função com as seguintes entradas:
# Teste 1
Entrada: 2, 3
Saída: 2^3 = 8
# Teste 2
Entrada: 4, 5
Saída: 4^5 = 1024
# Teste 3
Entrada: 6, 4
Saída: 6^4 = 1296
# Teste 4
Entrada: 34, 0
Saída: 34^0 = 1
Lembre-se de implementar a função calcular_potencia de forma recursiva, usando apenas operações matemáticas básicas.
10. Torre de Hanói: Um Desafio Recursivo da Computação e Matemática
A Torre de Hanói é um problema clássico e intrigante no campo da computação e matemática. Envolve a movimentação estratégica de discos entre três pinos, seguindo um conjunto específico de regras. O desafio parece simples à primeira vista, mas sua complexidade aumenta exponencialmente à medida que o número de discos cresce.
O Problema: Imagine três pinos, rotulados como A, B e C. No início do jogo, todos os discos, que variam em tamanho, estão empilhados em ordem decrescente de tamanho no pino A, com o disco maior embaixo e o menor no topo. O objetivo é transferir todos os discos do pino A para o pino C.
As Regras:
Você só pode mover um disco por vez.
Cada movimento envolve tirar o disco de cima de uma pilha e colocá-lo em cima de outra pilha.
Nunca coloque um disco maior em cima de um menor. Os discos devem ser empilhados em ordem de tamanho.
O pino B é auxiliar. Você pode usá-lo como um pino intermediário para ajudar na movimentação dos discos.
Visualizando o Jogo:
Estado inicial:
| | |
| | |
=== | |
===== | |
======= | |
-----------------------------
A B C
Estado intermediário (após mais duas jogadas):
| | |
| | |
| | |
| | |
======= ===== ===
-----------------------------
A B C
Estado final:
| | |
| | |
| | ===
| | =====
| | =======
-----------------------------
A B C
Sua Tarefa:
Implemente uma função recursiva chamada torre_de_hanoi que resolva esse problema. A função deve receber como entrada o número de discos (n) e os nomes dos pinos de origem, auxiliar e destino. Ela deve executar e imprimir os movimentos necessários para transferir todos os discos do pino de origem para o pino de destino.
Protótipo da Função:
def torre_de_hanoi(n, origem, auxiliar, destino):
# Implementação aqui
Dicas e Observações:
A função deve ter uma condição base para quando houver apenas um disco.
Use a recursividade para dividir o problema em subproblemas menores.
Imprima cada movimento no formato: “Mover disco de [origem] para [destino]”.
A solução recursiva deve:
Mover n-1 discos para o pino auxiliar
Mover o disco maior para o pino de destino
Mover os n-1 discos do pino auxiliar para o pino de destino
Testes:
# Teste 1
Entrada: 3, A, B, C
Saída:
Mover disco de A para C
Mover disco de A para B
Mover disco de C para B
Mover disco de A para C
Mover disco de B para A
Mover disco de B para C
Mover disco de A para C
# Teste 2
Entrada: 4, A, B, C
Saída:
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C
Mover disco de A para B
Mover disco de C para A
Mover disco de C para B
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C
Mover disco de B para A
Mover disco de C para A
Mover disco de B para C
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C
Exercícios (Extra)#
1. Analisador de Desempenho: Planeje seus Estudos!
A partir das notas de 7 disciplinas, calcule métricas de desempenho e gere um ranking de prioridade de estudo. Cada disciplina tem 3 unidades; o usuário fornece as 6 notas das duas primeiras unidades (3 avaliações cada), e o sistema calcula a nota necessária na 3ª unidade para atingir média 5.0.
Disciplinas (nesta ordem):
Linguagem de Programação
Álgebra Linear
Modelagem do Mundo Físico I
Práticas de Leitura e Escrita II
Química Geral
Cálculo Diferencial e Integral I
Meio Ambiente e Desenvolvimento Urbano
Entrada: 42 notas (7 disciplinas × 6 notas).
Métricas a calcular (por disciplina):
Média da unidade: \(\dfrac{\text{soma das 3 notas}}{3}\)
Nota necessária na 3ª unidade: \(3 \times 5.0 - (\text{Média 1ª} + \text{Média 2ª})\)
Consistência: \(1 - \dfrac{|\text{Média 2ª} - \text{Média 1ª}|}{\text{Média 1ª}}\) (próximo de 1 = estável; próximo de 0 = instável)
Instabilidade: \(\dfrac{\text{Desvio Padrão 2ª}}{\text{Desvio Padrão 1ª}}\) (=1 igual; >1 mais dispersa na 2ª; <1 mais dispersa na 1ª)
Prioridade: \(2.0 \times (1 - \text{Consistência}) + 1.5 \times \text{Instabilidade} + 1.0 \times \text{Nota Necessária}\)
Tarefa: implementar analisar_desempenho, que recebe as 42 notas e funções auxiliares, calcula as métricas e imprime o ranking ordenado por prioridade decrescente. Use sorted para ordenar.
Protótipo:
def analisar_desempenho(
notas: list[float],
calcular_media,
calcular_desvio_padrao,
calcular_nota_necessaria,
avaliar_consistencia,
gerar_ranking_prioridade
) -> None:
"""Analisa desempenho acadêmico e imprime o ranking de prioridade."""
pass
Teste:
# Teste 1
Entrada:
6.0, 7.0, 8.0, 5.0, 6.5, 6.0,
4.0, 5.5, 6.0, 4.5, 5.0, 4.0,
7.0, 8.0, 7.5, 6.0, 7.0, 6.5,
6.0, 6.5, 7.0, 6.0, 6.0, 5.5,
5.0, 5.5, 5.0, 4.5, 4.0, 4.0,
6.0, 7.0, 6.5, 5.5, 6.0, 5.0,
7.0, 6.5, 6.0, 6.5, 6.0, 5.5
Saída:
Ranking de prioridade para estudo:
1. Química Geral:
- Consistência: 0.81
- Instabilidade: 1.00
- Nota necessária na 3ª unidade: 5.67
- Prioridade: 7.55
2. Álgebra Linear:
- Consistência: 0.87
- Instabilidade: 0.48
- Nota necessária na 3ª unidade: 5.33
- Prioridade: 6.31
3. Cálculo Diferencial e Integral I:
- Consistência: 0.85
- Instabilidade: 1.00
- Nota necessária na 3ª unidade: 3.00
- Prioridade: 4.81
4. Meio Ambiente e Desenvolvimento Urbano:
- Consistência: 0.92
- Instabilidade: 1.00
- Nota necessária na 3ª unidade: 2.50
- Prioridade: 4.15
5. Práticas de Leitura e Escrita II:
- Consistência: 0.90
- Instabilidade: 0.58
- Nota necessária na 3ª unidade: 2.67
- Prioridade: 3.74
6. Linguagem de Programação:
- Consistência: 0.83
- Instabilidade: 0.76
- Nota necessária na 3ª unidade: 2.17
- Prioridade: 3.65
7. Modelagem do Mundo Físico I:
- Consistência: 0.87
- Instabilidade: 1.00
- Nota necessária na 3ª unidade: 1.00
- Prioridade: 2.77