Funções são um dos conceitos mais importantes em Python. Elas permitem organizar código, evitar repetição e criar programas mais legíveis e manuteníveis. Neste guia completo, você aprenderá desde o básico até técnicas avançadas de funções em Python.

🎯 Por Que Usar Funções?

Imagine que você precisa calcular a área de vários retângulos em seu programa. Sem funções, você teria que repetir o mesmo código várias vezes:

# Sem funções - código repetitivo
area1 = 5 * 3
area2 = 10 * 7
area3 = 8 * 4

print(f"Área 1: {area1}")
print(f"Área 2: {area2}")
print(f"Área 3: {area3}")

Com funções, você escreve o código uma vez e reutiliza quantas vezes precisar:

# Com funções - código reutilizável
def calcular_area(largura, altura):
    return largura * altura

area1 = calcular_area(5, 3)
area2 = calcular_area(10, 7)
area3 = calcular_area(8, 4)

print(f"Área 1: {area1}")
print(f"Área 2: {area2}")
print(f"Área 3: {area3}")

📝 Criando Sua Primeira Função

Para criar uma função em Python, use a palavra-chave def, seguida do nome da função e parênteses:

def saudacao():
    """Esta é uma docstring que descreve a função"""
    print("Olá! Bem-vindo ao Universo Python!")
    print("Vamos aprender sobre funções!")

# Chamar a função
saudacao()

Componentes de uma função:

  • def: palavra-chave que define uma função
  • saudacao: nome da função (use snake_case)
  • (): parênteses para parâmetros (vazio se não houver)
  • :: dois pontos marcam o início do bloco
  • Corpo indentado: código que será executado

🔄 Funções com Parâmetros

Parâmetros permitem passar informações para dentro da função:

def saudar_pessoa(nome):
    print(f"Olá, {nome}!")
    print(f"Seja bem-vindo ao nosso curso de Python!")

saudar_pessoa("Ana")     # Olá, Ana!
saudar_pessoa("Carlos")  # Olá, Carlos!

# Múltiplos parâmetros
def criar_perfil(nome, idade, cidade):
    print(f"Nome: {nome}")
    print(f"Idade: {idade} anos")
    print(f"Cidade: {cidade}")

criar_perfil("Maria", 28, "São Paulo")

Parâmetros com Valores Padrão

def cadastrar_usuario(nome, ativo=True, nivel="iniciante"):
    usuario = {
        "nome": nome,
        "ativo": ativo,
        "nivel": nivel
    }
    return usuario

# Usando valores padrão
user1 = cadastrar_usuario("Ana")
print(user1)  # {'nome': 'Ana', 'ativo': True, 'nivel': 'iniciante'}

# Sobrescrevendo valores padrão
user2 = cadastrar_usuario("Carlos", False, "avançado")
print(user2)  # {'nome': 'Carlos', 'ativo': False, 'nivel': 'avançado'}

Argumentos Nomeados (Keyword Arguments)

def criar_post(titulo, conteudo, autor, publicado=False):
    post = {
        "titulo": titulo,
        "conteudo": conteudo,
        "autor": autor,
        "publicado": publicado
    }
    return post

# Ordem não importa com argumentos nomeados
post = criar_post(
    conteudo="Aprendendo Python",
    autor="João",
    titulo="Meu Primeiro Post",
    publicado=True
)
print(post)

↩️ Retornando Valores

Use return para devolver um resultado da função. Isso é essencial para funções que calculam valores, como demonstrado em nosso guia de listas:

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

total = somar(10, 5)
print(total)  # 15

# Retornar múltiplos valores
def calcular_operacoes(a, b):
    soma = a + b
    subtracao = a - b
    multiplicacao = a * b
    divisao = a / b if b != 0 else None

    return soma, subtracao, multiplicacao, divisao

s, sub, m, d = calcular_operacoes(10, 5)
print(f"Soma: {s}, Subtração: {sub}, Multiplicação: {m}, Divisão: {d}")

⭐ *args - Argumentos Variáveis

Quando você não sabe quantos argumentos serão passados, use *args:

def somar_todos(*numeros):
    """Soma qualquer quantidade de números"""
    total = 0
    for numero in numeros:
        total += numero
    return total

print(somar_todos(1, 2, 3))              # 6
print(somar_todos(10, 20, 30, 40))       # 100
print(somar_todos(5))                    # 5
print(somar_todos(1, 2, 3, 4, 5, 6, 7))  # 28

# Exemplo prático: concatenar strings
def concatenar(*palavras):
    return " ".join(palavras)

frase = concatenar("Python", "é", "incrível!")
print(frase)  # Python é incrível!

🔑 **kwargs - Argumentos Nomeados Variáveis

Para aceitar qualquer número de argumentos nomeados, use **kwargs:

def criar_config(**opcoes):
    """Cria configuração com opções flexíveis"""
    config = {}
    for chave, valor in opcoes.items():
        config[chave] = valor
    return config

# Passar quantas opções quiser
conf = criar_config(
    tema="escuro",
    idioma="pt-br",
    notificacoes=True,
    volume=80,
    qualidade="HD"
)
print(conf)

# Combinando args e kwargs
def registrar_evento(evento, *detalhes, **metadata):
    print(f"Evento: {evento}")
    print(f"Detalhes: {detalhes}")
    print(f"Metadata: {metadata}")

registrar_evento(
    "login",
    "usuario123",
    "192.168.1.1",
    timestamp="2025-01-01",
    dispositivo="mobile"
)

🎨 Funções Lambda (Anônimas)

Lambdas são funções de uma linha, perfeitas para operações simples:

# Sintaxe: lambda argumentos: expressão

# Função tradicional
def quadrado(x):
    return x ** 2

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

print(quadrado_lambda(5))  # 25

# Útil com map, filter, sorted
numeros = [1, 2, 3, 4, 5]

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

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

# Ordenar lista de dicionários
pessoas = [
    {"nome": "Ana", "idade": 28},
    {"nome": "Bruno", "idade": 35},
    {"nome": "Carlos", "idade": 22}
]

# Ordenar por idade
ordenado = sorted(pessoas, key=lambda p: p["idade"])
print(ordenado)

🔁 Funções Recursivas

Uma função que chama a si mesma é recursiva. Útil para problemas que podem ser divididos em subproblemas menores:

def fatorial(n):
    """Calcula o fatorial de n usando recursão"""
    # Caso base
    if n == 0 or n == 1:
        return 1
    # Caso recursivo
    return n * fatorial(n - 1)

print(fatorial(5))  # 120 (5 * 4 * 3 * 2 * 1)
print(fatorial(7))  # 5040

# Fibonacci recursivo
def fibonacci(n):
    """Retorna o n-ésimo número de Fibonacci"""
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

# Primeiros 10 números
for i in range(10):
    print(fibonacci(i), end=" ")  # 0 1 1 2 3 5 8 13 21 34

# Contagem regressiva
def contagem_regressiva(numero):
    if numero <= 0:
        print("🚀 Lançamento!")
    else:
        print(numero)
        contagem_regressiva(numero - 1)

contagem_regressiva(5)

🎯 Escopo de Variáveis

Entender escopo é crucial. Variáveis têm diferentes "alcances" no código:

# Variável global
contador = 0

def incrementar():
    global contador  # Permite modificar global
    contador += 1
    return contador

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

# Variável local
def calcular():
    resultado = 10 * 5  # Local - só existe aqui
    return resultado

print(calcular())  # 50
# print(resultado)  # Erro! resultado não existe fora da função

# Variável nonlocal (em funções aninhadas)
def externa():
    mensagem = "Olá"

    def interna():
        nonlocal mensagem
        mensagem = "Olá, Python!"

    interna()
    print(mensagem)  # Olá, Python!

externa()

📚 Docstrings - Documentando Funções

Sempre documente suas funções! É uma boa prática essencial, especialmente quando trabalhamos com módulos e pacotes:

def calcular_imc(peso, altura):
    """
    Calcula o Índice de Massa Corporal (IMC).

    Parâmetros:
        peso (float): Peso em quilogramas
        altura (float): Altura em metros

    Retorna:
        float: Valor do IMC calculado

    Exemplo:
        >>> calcular_imc(70, 1.75)
        22.86

    Referência:
        IMC = peso / (altura²)
    """
    if altura <= 0:
        raise ValueError("Altura deve ser maior que zero")

    imc = peso / (altura ** 2)
    return round(imc, 2)

# Acessar docstring
print(calcular_imc.__doc__)
help(calcular_imc)

🎓 Projeto Prático: Sistema de Calculadora

Vamos criar uma calculadora completa usando tudo que aprendemos:

def somar(a, b):
    """Soma dois números"""
    return a + b

def subtrair(a, b):
    """Subtrai dois números"""
    return a - b

def multiplicar(a, b):
    """Multiplica dois números"""
    return a * b

def dividir(a, b):
    """Divide dois números"""
    if b == 0:
        return "Erro: Divisão por zero!"
    return a / b

def potencia(base, expoente):
    """Calcula base elevada ao expoente"""
    return base ** expoente

def raiz_quadrada(numero):
    """Calcula raiz quadrada"""
    if numero < 0:
        return "Erro: Número negativo!"
    return numero ** 0.5

def calculadora():
    """Sistema de calculadora interativo"""
    print("=" * 40)
    print("CALCULADORA PYTHON")
    print("=" * 40)

    operacoes = {
        "+": somar,
        "-": subtrair,
        "*": multiplicar,
        "/": dividir,
        "**": potencia,
        "sqrt": raiz_quadrada
    }

    print("\nOperações disponíveis:")
    print("+ (soma), - (subtração), * (multiplicação)")
    print("/ (divisão), ** (potência), sqrt (raiz)")

    while True:
        try:
            operacao = input("\nEscolha a operação (ou 'sair'): ").lower()

            if operacao == 'sair':
                print("Até logo!")
                break

            if operacao == 'sqrt':
                num = float(input("Digite o número: "))
                resultado = raiz_quadrada(num)
            elif operacao in operacoes:
                num1 = float(input("Primeiro número: "))
                num2 = float(input("Segundo número: "))
                resultado = operacoes[operacao](num1, num2)
            else:
                print("Operação inválida!")
                continue

            print(f"Resultado: {resultado}")

        except ValueError:
            print("Erro: Digite um número válido!")
        except Exception as e:
            print(f"Erro: {e}")

# Para usar: descomente a linha abaixo
# calculadora()

💡 Boas Práticas com Funções

  1. Use nomes descritivos: calcular_total() é melhor que calc()
  2. Faça uma coisa bem: Cada função deve ter uma responsabilidade clara
  3. Mantenha funções pequenas: Idealmente, menos de 20 linhas
  4. Evite efeitos colaterais: Prefira retornar valores a modificar variáveis globais
  5. Documente sempre: Use docstrings para funções públicas
  6. Validação de entrada: Verifique os parâmetros recebidos

🔗 Próximos Passos

Agora que você domina funções, explore tópicos relacionados:

Quer se tornar um desenvolvedor Python profissional? Confira nosso curso completo de Python do zero ao avançado com projetos práticos e certificado!