Funções são blocos de código reutilizáveis que executam uma tarefa específica. Elas são fundamentais para escrever código organizado, legível e fácil de manter. Neste guia, você vai aprender tudo sobre funções em Python, desde a criação básica até conceitos avançados.

🎯 O Que São Funções e Por Que Usá-las?

Imagine que você precisa calcular a média de notas em vários lugares do seu programa. Sem funções, você teria que repetir o mesmo código várias vezes. Com funções, você escreve uma vez e reutiliza quantas vezes quiser.

Vantagens de usar funções:

  • Reutilização: escreva uma vez, use várias vezes
  • Organização: código dividido em blocos lógicos
  • Manutenção: corrija em um lugar, funciona em todos
  • Legibilidade: nomes descritivos explicam o que o código faz
  • Testabilidade: funções isoladas são mais fáceis de testar

📝 Criando Sua Primeira Função

Em Python, usamos a palavra-chave def para definir uma função:

def saudacao():
    print("Olá, seja bem-vindo!")

# Chamando a função
saudacao()  # Saída: Olá, seja bem-vindo!

A estrutura básica é:

  • def indica que estamos definindo uma função
  • saudacao é o nome da função
  • () são os parênteses para parâmetros (vazio neste caso)
  • : indica o início do bloco de código
  • O código indentado faz parte da função

📥 Parâmetros e Argumentos

Parâmetros permitem que você passe informações para a função:

def saudacao(nome):
    print(f"Olá, {nome}!")

saudacao("Maria")   # Olá, Maria!
saudacao("João")    # Olá, João!

Múltiplos Parâmetros

def apresentar(nome, idade, cidade):
    print(f"{nome} tem {idade} anos e mora em {cidade}")

apresentar("Ana", 25, "São Paulo")
# Ana tem 25 anos e mora em São Paulo

Parâmetros com Valores Padrão

Você pode definir valores padrão que serão usados caso o argumento não seja fornecido:

def saudacao(nome, cumprimento="Olá"):
    print(f"{cumprimento}, {nome}!")

saudacao("Carlos")              # Olá, Carlos!
saudacao("Carlos", "Bem-vindo") # Bem-vindo, Carlos!

Importante: parâmetros com valores padrão devem vir depois dos parâmetros obrigatórios.

Argumentos Nomeados (Keyword Arguments)

Você pode especificar argumentos pelo nome, independente da ordem:

def criar_perfil(nome, idade, profissao):
    print(f"Nome: {nome}, Idade: {idade}, Profissão: {profissao}")

# Argumentos por posição
criar_perfil("Ana", 30, "Desenvolvedora")

# Argumentos nomeados (qualquer ordem)
criar_perfil(profissao="Designer", nome="Bruno", idade=28)

📤 Retornando Valores

Use return para que a função devolva um resultado:

def somar(a, b):
    return a + b

resultado = somar(5, 3)
print(resultado)  # 8

# Usando diretamente
print(somar(10, 20))  # 30

Retornando Múltiplos Valores

Python permite retornar múltiplos valores como uma tupla:

def calcular(a, b):
    soma = a + b
    diferenca = a - b
    produto = a * b
    return soma, diferenca, produto

s, d, p = calcular(10, 5)
print(f"Soma: {s}, Diferença: {d}, Produto: {p}")
# Soma: 15, Diferença: 5, Produto: 50

Return Antecipado

Você pode usar return para sair da função antes do final:

def dividir(a, b):
    if b == 0:
        return "Erro: divisão por zero"
    return a / b

print(dividir(10, 2))  # 5.0
print(dividir(10, 0))  # Erro: divisão por zero

📦 *args e **kwargs

*args (Argumentos Posicionais Variáveis)

Permite receber um número indefinido de argumentos:

def somar_todos(*numeros):
    total = 0
    for num in numeros:
        total += num
    return total

print(somar_todos(1, 2, 3))       # 6
print(somar_todos(1, 2, 3, 4, 5)) # 15

**kwargs (Argumentos Nomeados Variáveis)

Permite receber argumentos nomeados como um dicionário:

def criar_usuario(**dados):
    for chave, valor in dados.items():
        print(f"{chave}: {valor}")

criar_usuario(nome="Ana", idade=25, email="[email protected]")
# nome: Ana
# idade: 25
# email: [email protected]

🔄 Escopo de Variáveis

Variáveis criadas dentro de uma função são locais (existem apenas dentro dela):

def minha_funcao():
    variavel_local = "Só existo aqui dentro"
    print(variavel_local)

minha_funcao()
# print(variavel_local)  # Erro! Variável não existe fora da função

Variáveis Globais

contador = 0

def incrementar():
    global contador
    contador += 1

incrementar()
incrementar()
print(contador)  # 2

Dica: evite usar global. Prefira passar valores como parâmetros e retornar resultados.

📚 Funções Lambda (Anônimas)

Funções lambda são funções pequenas e anônimas, definidas em uma única linha:

# Função normal
def dobrar(x):
    return x * 2

# Equivalente em lambda
dobrar = lambda x: x * 2

print(dobrar(5))  # 10

Lambdas são úteis com funções como map, filter e sorted:

numeros = [1, 2, 3, 4, 5]

# Dobrar todos os números
dobrados = list(map(lambda x: x * 2, numeros))
print(dobrados)  # [2, 4, 6, 8, 10]

# Filtrar pares
pares = list(filter(lambda x: x % 2 == 0, numeros))
print(pares)  # [2, 4]

# Ordenar lista de nomes pelo último caractere
nomes = ["Ana", "Bruno", "Carla"]
ordenados = sorted(nomes, key=lambda nome: nome[-1])
print(ordenados)  # ["Ana", "Carla", "Bruno"]

🎮 Projetos Práticos

1. Calculadora de IMC

def calcular_imc(peso, altura):
    imc = peso / (altura ** 2)
    
    if imc < 18.5:
        categoria = "Abaixo do peso"
    elif imc < 25:
        categoria = "Peso normal"
    elif imc < 30:
        categoria = "Sobrepeso"
    else:
        categoria = "Obesidade"
    
    return imc, categoria

peso = float(input("Peso (kg): "))
altura = float(input("Altura (m): "))

imc, categoria = calcular_imc(peso, altura)
print(f"IMC: {imc:.2f}")
print(f"Categoria: {categoria}")

2. Validador de Senha

def validar_senha(senha):
    erros = []
    
    if len(senha) < 8:
        erros.append("Mínimo 8 caracteres")
    
    if not any(c.isupper() for c in senha):
        erros.append("Precisa de letra maiúscula")
    
    if not any(c.islower() for c in senha):
        erros.append("Precisa de letra minúscula")
    
    if not any(c.isdigit() for c in senha):
        erros.append("Precisa de número")
    
    if erros:
        return False, erros
    return True, ["Senha válida!"]

valida, mensagens = validar_senha("Abc12345")
for msg in mensagens:
    print(msg)

💡 Boas Práticas

1. Nomes Descritivos

# Ruim
def f(x, y):
    return x * y

# Bom
def calcular_area_retangulo(base, altura):
    return base * altura

2. Uma Função, Uma Responsabilidade

Cada função deve fazer apenas uma coisa. Se sua função faz muitas coisas, divida em funções menores.

3. Docstrings

def calcular_desconto(preco, percentual):
    """
    Calcula o preço com desconto aplicado.
    
    Args:
        preco: Preço original do produto
        percentual: Percentual de desconto (0-100)
    
    Returns:
        Preço final com desconto aplicado
    """
    desconto = preco * (percentual / 100)
    return preco - desconto

🚀 Próximos Passos

Agora que você domina funções básicas, está pronto para aprender sobre decorators e generators, que são conceitos avançados que usam funções como base. Também recomendo explorar módulos e pacotes para organizar suas funções em arquivos separados.

Se você ainda está começando, revise o conteúdo sobre estruturas condicionais e listas, que são muito usados dentro de funções.

Para um aprendizado completo e estruturado, confira nosso curso de Python do zero ao avançado.

Continue praticando! Quanto mais funções você criar, mais natural será o processo.