Voltar ao Glossario
Glossario Python

Funcao: O que É e Como Funciona | Python Brasil

Aprenda tudo sobre funcoes em Python: definicao, parametros, retorno, escopo, closures, decoradores e boas praticas para organizar seu codigo.

O que e uma Funcao?

Uma funcao em Python e um bloco de codigo reutilizavel que executa uma tarefa especifica. Funcoes sao a principal ferramenta de abstracao e organizacao da linguagem, permitindo dividir programas complexos em partes menores, mais legiveis e mais faceis de manter. Em Python, funcoes sao definidas com a palavra-chave def e sao objetos de primeira classe, o que significa que podem ser atribuidas a variaveis, passadas como argumentos e retornadas por outras funcoes.

Como Definir Funcoes

# Funcao simples
def saudacao():
    print('Ola, mundo!')

saudacao()  # Ola, mundo!

# Funcao com parametros e retorno
def somar(a, b):
    return a + b

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

# Funcao com docstring
def calcular_area(base, altura):
    """Calcula a area de um triangulo.

    Args:
        base (float): A base do triangulo.
        altura (float): A altura do triangulo.

    Returns:
        float: A area calculada.
    """
    return (base * altura) / 2

Tipos de Parametros

Python oferece grande flexibilidade na definicao de parametros de funcoes.

# Parametros posicionais e com valor padrao
def criar_usuario(nome, email, ativo=True):
    return {'nome': nome, 'email': email, 'ativo': ativo}

usuario = criar_usuario('Ana', 'ana@email.com')
usuario2 = criar_usuario('Bruno', 'bruno@email.com', ativo=False)

# *args — numero variavel de argumentos posicionais
def calcular_media(*notas):
    if not notas:
        return 0
    return sum(notas) / len(notas)

print(calcular_media(7.5, 8.0, 9.0))  # 8.166...
print(calcular_media(10, 9))           # 9.5

# **kwargs — numero variavel de argumentos nomeados
def criar_perfil(nome, **detalhes):
    perfil = {'nome': nome}
    perfil.update(detalhes)
    return perfil

perfil = criar_perfil('Ana', cidade='Sao Paulo', idade=28)
print(perfil)  # {'nome': 'Ana', 'cidade': 'Sao Paulo', 'idade': 28}

# Parametros somente posicionais (/) e somente nomeados (*)
def dividir(a, b, /, *, arredondar=False):
    resultado = a / b
    if arredondar:
        return round(resultado, 2)
    return resultado

print(dividir(10, 3, arredondar=True))  # 3.33

Retorno de Valores

# Retorno simples
def quadrado(n):
    return n ** 2

# Retorno multiplo (na verdade retorna uma tupla)
def dividir_com_resto(a, b):
    quociente = a // b
    resto = a % b
    return quociente, resto

q, r = dividir_com_resto(17, 5)
print(f'Quociente: {q}, Resto: {r}')  # Quociente: 3, Resto: 2

# Funcao sem return explicito retorna None
def apenas_imprime(msg):
    print(msg)

resultado = apenas_imprime('oi')
print(resultado)  # None

Escopo de Variaveis

O escopo determina onde uma variavel e acessivel. Python segue a regra LEGB: Local, Enclosing, Global, Built-in.

x = 'global'

def funcao_externa():
    x = 'enclosing'

    def funcao_interna():
        x = 'local'
        print(x)  # 'local'

    funcao_interna()
    print(x)  # 'enclosing'

funcao_externa()
print(x)  # 'global'

# Usando global e nonlocal
contador = 0

def incrementar():
    global contador
    contador += 1

def funcao_externa2():
    valor = 10

    def funcao_interna2():
        nonlocal valor
        valor += 5

    funcao_interna2()
    print(valor)  # 15

Funcoes como Objetos de Primeira Classe

# Atribuir funcao a variavel
def gritar(texto):
    return texto.upper()

funcao = gritar
print(funcao('ola'))  # 'OLA'

# Passar funcao como argumento
def aplicar(funcao, valor):
    return funcao(valor)

print(aplicar(abs, -42))       # 42
print(aplicar(str.upper, 'a')) # 'A'

# Retornar funcao de outra funcao
def multiplicador(fator):
    def multiplicar(numero):
        return numero * fator
    return multiplicar

dobro = multiplicador(2)
triplo = multiplicador(3)
print(dobro(5))   # 10
print(triplo(5))  # 15

Closures

Uma closure e uma funcao interna que “lembra” das variaveis do escopo onde foi definida, mesmo apos a funcao externa ter terminado.

def criar_contador(inicio=0):
    contagem = [inicio]  # lista para contornar a imutabilidade

    def contar():
        contagem[0] += 1
        return contagem[0]

    return contar

contador = criar_contador()
print(contador())  # 1
print(contador())  # 2
print(contador())  # 3

Type Hints em Funcoes

def buscar_usuario(user_id: int) -> dict | None:
    """Busca um usuario pelo ID."""
    usuarios = {1: {'nome': 'Ana'}, 2: {'nome': 'Bruno'}}
    return usuarios.get(user_id)

def processar_itens(itens: list[str], limite: int = 10) -> list[str]:
    """Processa e retorna no maximo 'limite' itens."""
    return [item.strip().lower() for item in itens[:limite]]

Erros Comuns

O erro mais frequente e usar objetos mutaveis como valores padrao de parametros, como def func(lista=[]). O Python avalia o valor padrao apenas uma vez, fazendo com que chamadas diferentes compartilhem o mesmo objeto. O correto e usar None e criar o objeto dentro da funcao. Outro erro comum e esquecer os parenteses ao chamar uma funcao, resultando em uma referencia ao objeto funcao em vez de sua execucao. Tambem e comum confundir return com print — funcoes que apenas imprimem valores nao permitem que o resultado seja usado em outras partes do codigo.

Boas Praticas

Cada funcao deve ter uma unica responsabilidade, seguindo o principio de responsabilidade unica. Nomes de funcoes devem ser descritivos e usar snake_case. Inclua docstrings que expliquem o proposito, parametros e retorno. Use type hints para documentar os tipos esperados. Mantenha funcoes curtas — se uma funcao tem mais de 20-30 linhas, considere dividi-la. Evite efeitos colaterais inesperados e prefira funcoes puras sempre que possivel.

Quando Usar

Funcoes devem ser usadas sempre que um trecho de codigo se repete ou quando voce quer isolar uma logica especifica. Elas sao a base para construir programas modulares, testaveis e faceis de manter. Mesmo trechos de codigo executados apenas uma vez podem se beneficiar de estar em uma funcao, pois o nome da funcao documenta a intencao do codigo.